mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 06:02:56 +00:00
[SAMSRV]
Clean-up the setup code: - Use SampRegXxx functions instead of RegXxx functions. - Let the setup functions return NTSTATUS instead of BOOL. - Use a separate function to create the server object. svn path=/trunk/; revision=59282
This commit is contained in:
parent
b5de08425e
commit
1edd94dfa6
1 changed files with 446 additions and 387 deletions
|
@ -88,63 +88,71 @@ SampSetupAddMemberToAlias(HKEY hDomainKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static BOOL
|
static
|
||||||
SampSetupCreateAliasAccount(HKEY hDomainKey,
|
NTSTATUS
|
||||||
|
SampSetupCreateAliasAccount(HANDLE hDomainKey,
|
||||||
LPCWSTR lpAccountName,
|
LPCWSTR lpAccountName,
|
||||||
LPCWSTR lpDescription,
|
LPCWSTR lpDescription,
|
||||||
ULONG ulRelativeId)
|
ULONG ulRelativeId)
|
||||||
{
|
{
|
||||||
DWORD dwDisposition;
|
|
||||||
WCHAR szAccountKeyName[32];
|
WCHAR szAccountKeyName[32];
|
||||||
HKEY hAccountKey = NULL;
|
HANDLE hAccountKey = NULL;
|
||||||
HKEY hNamesKey = NULL;
|
HANDLE hNamesKey = NULL;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
swprintf(szAccountKeyName, L"Aliases\\%08lX", ulRelativeId);
|
swprintf(szAccountKeyName, L"Aliases\\%08lX", ulRelativeId);
|
||||||
|
|
||||||
if (!RegCreateKeyExW(hDomainKey,
|
Status = SampRegCreateKey(hDomainKey,
|
||||||
szAccountKeyName,
|
szAccountKeyName,
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
REG_OPTION_NON_VOLATILE,
|
|
||||||
KEY_ALL_ACCESS,
|
KEY_ALL_ACCESS,
|
||||||
NULL,
|
&hAccountKey);
|
||||||
&hAccountKey,
|
if (!NT_SUCCESS(Status))
|
||||||
&dwDisposition))
|
return Status;
|
||||||
{
|
|
||||||
RegSetValueEx(hAccountKey,
|
Status = SampRegSetValue(hAccountKey,
|
||||||
L"Name",
|
L"Name",
|
||||||
0,
|
|
||||||
REG_SZ,
|
REG_SZ,
|
||||||
(LPVOID)lpAccountName,
|
(LPVOID)lpAccountName,
|
||||||
(wcslen(lpAccountName) + 1) * sizeof(WCHAR));
|
(wcslen(lpAccountName) + 1) * sizeof(WCHAR));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
|
|
||||||
RegSetValueEx(hAccountKey,
|
Status = SampRegSetValue(hAccountKey,
|
||||||
L"Description",
|
L"Description",
|
||||||
0,
|
|
||||||
REG_SZ,
|
REG_SZ,
|
||||||
(LPVOID)lpDescription,
|
(LPVOID)lpDescription,
|
||||||
(wcslen(lpDescription) + 1) * sizeof(WCHAR));
|
(wcslen(lpDescription) + 1) * sizeof(WCHAR));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
|
|
||||||
RegCloseKey(hAccountKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!RegOpenKeyExW(hDomainKey,
|
Status = SampRegOpenKey(hDomainKey,
|
||||||
L"Aliases\\Names",
|
L"Aliases\\Names",
|
||||||
0,
|
|
||||||
KEY_ALL_ACCESS,
|
KEY_ALL_ACCESS,
|
||||||
&hNamesKey))
|
&hNamesKey);
|
||||||
{
|
if (!NT_SUCCESS(Status))
|
||||||
RegSetValueEx(hNamesKey,
|
goto done;
|
||||||
|
|
||||||
|
Status = SampRegSetValue(hNamesKey,
|
||||||
lpAccountName,
|
lpAccountName,
|
||||||
0,
|
|
||||||
REG_DWORD,
|
REG_DWORD,
|
||||||
(LPVOID)&ulRelativeId,
|
(LPVOID)&ulRelativeId,
|
||||||
sizeof(ULONG));
|
sizeof(ULONG));
|
||||||
|
|
||||||
RegCloseKey(hNamesKey);
|
done:
|
||||||
|
if (hNamesKey != NULL)
|
||||||
|
SampRegCloseKey(hNamesKey);
|
||||||
|
|
||||||
|
if (hAccountKey != NULL)
|
||||||
|
{
|
||||||
|
SampRegCloseKey(hAccountKey);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
SampRegDeleteKey(hDomainKey,
|
||||||
|
szAccountKeyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -310,8 +318,9 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static BOOL
|
static
|
||||||
SampSetupCreateUserAccount(HKEY hDomainKey,
|
NTSTATUS
|
||||||
|
SampSetupCreateUserAccount(HANDLE hDomainKey,
|
||||||
LPCWSTR lpAccountName,
|
LPCWSTR lpAccountName,
|
||||||
LPCWSTR lpComment,
|
LPCWSTR lpComment,
|
||||||
ULONG ulRelativeId,
|
ULONG ulRelativeId,
|
||||||
|
@ -321,10 +330,10 @@ SampSetupCreateUserAccount(HKEY hDomainKey,
|
||||||
GROUP_MEMBERSHIP GroupMembership;
|
GROUP_MEMBERSHIP GroupMembership;
|
||||||
UCHAR LogonHours[23];
|
UCHAR LogonHours[23];
|
||||||
LPWSTR lpEmptyString = L"";
|
LPWSTR lpEmptyString = L"";
|
||||||
DWORD dwDisposition;
|
|
||||||
WCHAR szAccountKeyName[32];
|
WCHAR szAccountKeyName[32];
|
||||||
HKEY hAccountKey = NULL;
|
HANDLE hAccountKey = NULL;
|
||||||
HKEY hNamesKey = NULL;
|
HANDLE hNamesKey = NULL;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
/* Initialize fixed user data */
|
/* Initialize fixed user data */
|
||||||
FixedUserData.Version = 1;
|
FixedUserData.Version = 1;
|
||||||
|
@ -347,103 +356,112 @@ SampSetupCreateUserAccount(HKEY hDomainKey,
|
||||||
|
|
||||||
swprintf(szAccountKeyName, L"Users\\%08lX", ulRelativeId);
|
swprintf(szAccountKeyName, L"Users\\%08lX", ulRelativeId);
|
||||||
|
|
||||||
if (!RegCreateKeyExW(hDomainKey,
|
Status = SampRegCreateKey(hDomainKey,
|
||||||
szAccountKeyName,
|
szAccountKeyName,
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
REG_OPTION_NON_VOLATILE,
|
|
||||||
KEY_ALL_ACCESS,
|
KEY_ALL_ACCESS,
|
||||||
NULL,
|
&hAccountKey);
|
||||||
&hAccountKey,
|
if (!NT_SUCCESS(Status))
|
||||||
&dwDisposition))
|
return Status;
|
||||||
{
|
|
||||||
RegSetValueEx(hAccountKey,
|
Status = SampRegSetValue(hAccountKey,
|
||||||
L"F",
|
L"F",
|
||||||
0,
|
|
||||||
REG_BINARY,
|
REG_BINARY,
|
||||||
(LPVOID)&FixedUserData,
|
(LPVOID)&FixedUserData,
|
||||||
sizeof(SAM_USER_FIXED_DATA));
|
sizeof(SAM_USER_FIXED_DATA));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
|
|
||||||
RegSetValueEx(hAccountKey,
|
Status = SampRegSetValue(hAccountKey,
|
||||||
L"Name",
|
L"Name",
|
||||||
0,
|
|
||||||
REG_SZ,
|
REG_SZ,
|
||||||
(LPVOID)lpAccountName,
|
(LPVOID)lpAccountName,
|
||||||
(wcslen(lpAccountName) + 1) * sizeof(WCHAR));
|
(wcslen(lpAccountName) + 1) * sizeof(WCHAR));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
|
|
||||||
RegSetValueEx(hAccountKey,
|
Status = SampRegSetValue(hAccountKey,
|
||||||
L"FullName",
|
L"FullName",
|
||||||
0,
|
|
||||||
REG_SZ,
|
REG_SZ,
|
||||||
(LPVOID)lpEmptyString,
|
(LPVOID)lpEmptyString,
|
||||||
sizeof(WCHAR));
|
sizeof(WCHAR));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
|
|
||||||
RegSetValueEx(hAccountKey,
|
Status = SampRegSetValue(hAccountKey,
|
||||||
L"HomeDirectory",
|
L"HomeDirectory",
|
||||||
0,
|
|
||||||
REG_SZ,
|
REG_SZ,
|
||||||
(LPVOID)lpEmptyString,
|
(LPVOID)lpEmptyString,
|
||||||
sizeof(WCHAR));
|
sizeof(WCHAR));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
|
|
||||||
RegSetValueEx(hAccountKey,
|
Status = SampRegSetValue(hAccountKey,
|
||||||
L"HomeDirectoryDrive",
|
L"HomeDirectoryDrive",
|
||||||
0,
|
|
||||||
REG_SZ,
|
REG_SZ,
|
||||||
(LPVOID)lpEmptyString,
|
(LPVOID)lpEmptyString,
|
||||||
sizeof(WCHAR));
|
sizeof(WCHAR));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
|
|
||||||
RegSetValueEx(hAccountKey,
|
Status = SampRegSetValue(hAccountKey,
|
||||||
L"ScriptPath",
|
L"ScriptPath",
|
||||||
0,
|
|
||||||
REG_SZ,
|
REG_SZ,
|
||||||
(LPVOID)lpEmptyString,
|
(LPVOID)lpEmptyString,
|
||||||
sizeof(WCHAR));
|
sizeof(WCHAR));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
|
|
||||||
RegSetValueEx(hAccountKey,
|
Status = SampRegSetValue(hAccountKey,
|
||||||
L"ProfilePath",
|
L"ProfilePath",
|
||||||
0,
|
|
||||||
REG_SZ,
|
REG_SZ,
|
||||||
(LPVOID)lpEmptyString,
|
(LPVOID)lpEmptyString,
|
||||||
sizeof(WCHAR));
|
sizeof(WCHAR));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
|
|
||||||
RegSetValueEx(hAccountKey,
|
Status = SampRegSetValue(hAccountKey,
|
||||||
L"AdminComment",
|
L"AdminComment",
|
||||||
0,
|
|
||||||
REG_SZ,
|
REG_SZ,
|
||||||
(LPVOID)lpComment,
|
(LPVOID)lpComment,
|
||||||
(wcslen(lpComment) + 1) * sizeof(WCHAR));
|
(wcslen(lpComment) + 1) * sizeof(WCHAR));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
|
|
||||||
RegSetValueEx(hAccountKey,
|
Status = SampRegSetValue(hAccountKey,
|
||||||
L"UserComment",
|
L"UserComment",
|
||||||
0,
|
|
||||||
REG_SZ,
|
REG_SZ,
|
||||||
(LPVOID)lpEmptyString,
|
(LPVOID)lpEmptyString,
|
||||||
sizeof(WCHAR));
|
sizeof(WCHAR));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
|
|
||||||
RegSetValueEx(hAccountKey,
|
Status = SampRegSetValue(hAccountKey,
|
||||||
L"WorkStations",
|
L"WorkStations",
|
||||||
0,
|
|
||||||
REG_SZ,
|
REG_SZ,
|
||||||
(LPVOID)lpEmptyString,
|
(LPVOID)lpEmptyString,
|
||||||
sizeof(WCHAR));
|
sizeof(WCHAR));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
|
|
||||||
RegSetValueEx(hAccountKey,
|
Status = SampRegSetValue(hAccountKey,
|
||||||
L"Parameters",
|
L"Parameters",
|
||||||
0,
|
|
||||||
REG_SZ,
|
REG_SZ,
|
||||||
(LPVOID)lpEmptyString,
|
(LPVOID)lpEmptyString,
|
||||||
sizeof(WCHAR));
|
sizeof(WCHAR));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
|
|
||||||
/* Set LogonHours attribute*/
|
/* Set LogonHours attribute*/
|
||||||
*((PUSHORT)LogonHours) = 168;
|
*((PUSHORT)LogonHours) = 168;
|
||||||
memset(&(LogonHours[2]), 0xff, 21);
|
memset(&(LogonHours[2]), 0xff, 21);
|
||||||
|
|
||||||
RegSetValueEx(hAccountKey,
|
Status = SampRegSetValue(hAccountKey,
|
||||||
L"LogonHours",
|
L"LogonHours",
|
||||||
0,
|
|
||||||
REG_BINARY,
|
REG_BINARY,
|
||||||
(LPVOID)LogonHours,
|
(LPVOID)LogonHours,
|
||||||
sizeof(LogonHours));
|
sizeof(LogonHours));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
|
|
||||||
/* Set Groups attribute*/
|
/* Set Groups attribute*/
|
||||||
GroupMembership.RelativeId = DOMAIN_GROUP_RID_USERS;
|
GroupMembership.RelativeId = DOMAIN_GROUP_RID_USERS;
|
||||||
|
@ -451,85 +469,100 @@ SampSetupCreateUserAccount(HKEY hDomainKey,
|
||||||
SE_GROUP_ENABLED |
|
SE_GROUP_ENABLED |
|
||||||
SE_GROUP_ENABLED_BY_DEFAULT;
|
SE_GROUP_ENABLED_BY_DEFAULT;
|
||||||
|
|
||||||
RegSetValueEx(hAccountKey,
|
Status = SampRegSetValue(hAccountKey,
|
||||||
L"Groups",
|
L"Groups",
|
||||||
0,
|
|
||||||
REG_BINARY,
|
REG_BINARY,
|
||||||
(LPVOID)&GroupMembership,
|
(LPVOID)&GroupMembership,
|
||||||
sizeof(GROUP_MEMBERSHIP));
|
sizeof(GROUP_MEMBERSHIP));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
|
|
||||||
/* Set LMPwd attribute*/
|
/* Set LMPwd attribute*/
|
||||||
RegSetValueEx(hAccountKey,
|
Status = SampRegSetValue(hAccountKey,
|
||||||
L"LMPwd",
|
L"LMPwd",
|
||||||
0,
|
|
||||||
REG_BINARY,
|
REG_BINARY,
|
||||||
(LPVOID)&EmptyLmHash,
|
(LPVOID)&EmptyLmHash,
|
||||||
sizeof(ENCRYPTED_LM_OWF_PASSWORD));
|
sizeof(ENCRYPTED_LM_OWF_PASSWORD));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
|
|
||||||
/* Set NTPwd attribute*/
|
/* Set NTPwd attribute*/
|
||||||
RegSetValueEx(hAccountKey,
|
Status = SampRegSetValue(hAccountKey,
|
||||||
L"NTPwd",
|
L"NTPwd",
|
||||||
0,
|
|
||||||
REG_BINARY,
|
REG_BINARY,
|
||||||
(LPVOID)&EmptyNtHash,
|
(LPVOID)&EmptyNtHash,
|
||||||
sizeof(ENCRYPTED_NT_OWF_PASSWORD));
|
sizeof(ENCRYPTED_NT_OWF_PASSWORD));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
|
|
||||||
/* Set LMPwdHistory attribute*/
|
/* Set LMPwdHistory attribute*/
|
||||||
RegSetValueEx(hAccountKey,
|
Status = SampRegSetValue(hAccountKey,
|
||||||
L"LMPwdHistory",
|
L"LMPwdHistory",
|
||||||
0,
|
|
||||||
REG_BINARY,
|
REG_BINARY,
|
||||||
NULL,
|
NULL,
|
||||||
0);
|
0);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
|
|
||||||
/* Set NTPwdHistory attribute*/
|
/* Set NTPwdHistory attribute*/
|
||||||
RegSetValueEx(hAccountKey,
|
Status = SampRegSetValue(hAccountKey,
|
||||||
L"NTPwdHistory",
|
L"NTPwdHistory",
|
||||||
0,
|
|
||||||
REG_BINARY,
|
REG_BINARY,
|
||||||
NULL,
|
NULL,
|
||||||
0);
|
0);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
|
|
||||||
/* FIXME: Set SecDesc attribute*/
|
/* FIXME: Set SecDesc attribute*/
|
||||||
|
|
||||||
RegCloseKey(hAccountKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!RegOpenKeyExW(hDomainKey,
|
Status = SampRegOpenKey(hDomainKey,
|
||||||
L"Users\\Names",
|
L"Users\\Names",
|
||||||
0,
|
|
||||||
KEY_ALL_ACCESS,
|
KEY_ALL_ACCESS,
|
||||||
&hNamesKey))
|
&hNamesKey);
|
||||||
{
|
if (!NT_SUCCESS(Status))
|
||||||
RegSetValueEx(hNamesKey,
|
goto done;
|
||||||
|
|
||||||
|
Status = SampRegSetValue(hNamesKey,
|
||||||
lpAccountName,
|
lpAccountName,
|
||||||
0,
|
|
||||||
REG_DWORD,
|
REG_DWORD,
|
||||||
(LPVOID)&ulRelativeId,
|
(LPVOID)&ulRelativeId,
|
||||||
sizeof(ULONG));
|
sizeof(ULONG));
|
||||||
|
|
||||||
RegCloseKey(hNamesKey);
|
done:
|
||||||
|
if (hNamesKey != NULL)
|
||||||
|
SampRegCloseKey(hNamesKey);
|
||||||
|
|
||||||
|
if (hAccountKey != NULL)
|
||||||
|
{
|
||||||
|
SampRegCloseKey(hAccountKey);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
SampRegDeleteKey(hDomainKey,
|
||||||
|
szAccountKeyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static BOOL
|
static
|
||||||
SampSetupCreateDomain(IN HKEY hDomainsKey,
|
NTSTATUS
|
||||||
|
SampSetupCreateDomain(IN HANDLE hServerKey,
|
||||||
IN LPCWSTR lpKeyName,
|
IN LPCWSTR lpKeyName,
|
||||||
IN LPCWSTR lpDomainName,
|
IN LPCWSTR lpDomainName,
|
||||||
IN PSID lpDomainSid,
|
IN PSID lpDomainSid,
|
||||||
OUT PHKEY lpDomainKey)
|
OUT HANDLE *lpDomainKey)
|
||||||
{
|
{
|
||||||
SAM_DOMAIN_FIXED_DATA FixedData;
|
SAM_DOMAIN_FIXED_DATA FixedData;
|
||||||
|
WCHAR szDomainKeyName[32];
|
||||||
LPWSTR lpEmptyString = L"";
|
LPWSTR lpEmptyString = L"";
|
||||||
DWORD dwDisposition;
|
HANDLE hDomainKey = NULL;
|
||||||
HKEY hDomainKey = NULL;
|
HANDLE hAliasesKey = NULL;
|
||||||
HKEY hAliasesKey = NULL;
|
HANDLE hGroupsKey = NULL;
|
||||||
HKEY hGroupsKey = NULL;
|
HANDLE hUsersKey = NULL;
|
||||||
HKEY hUsersKey = NULL;
|
HANDLE hNamesKey = NULL;
|
||||||
HKEY hNamesKey = NULL;
|
NTSTATUS Status;
|
||||||
|
|
||||||
if (lpDomainKey != NULL)
|
if (lpDomainKey != NULL)
|
||||||
*lpDomainKey = NULL;
|
*lpDomainKey = NULL;
|
||||||
|
@ -554,137 +587,164 @@ SampSetupCreateDomain(IN HKEY hDomainsKey,
|
||||||
FixedData.DomainServerRole = DomainServerRolePrimary;
|
FixedData.DomainServerRole = DomainServerRolePrimary;
|
||||||
FixedData.UasCompatibilityRequired = TRUE;
|
FixedData.UasCompatibilityRequired = TRUE;
|
||||||
|
|
||||||
if (RegCreateKeyExW(hDomainsKey,
|
wcscpy(szDomainKeyName, L"Domains\\");
|
||||||
lpKeyName,
|
wcscat(szDomainKeyName, lpKeyName);
|
||||||
0,
|
|
||||||
NULL,
|
Status = SampRegCreateKey(hServerKey,
|
||||||
REG_OPTION_NON_VOLATILE,
|
szDomainKeyName,
|
||||||
KEY_ALL_ACCESS,
|
KEY_ALL_ACCESS,
|
||||||
NULL,
|
&hDomainKey);
|
||||||
&hDomainKey,
|
if (!NT_SUCCESS(Status))
|
||||||
&dwDisposition))
|
return Status;
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* Set the fixed data value */
|
/* Set the fixed data value */
|
||||||
if (RegSetValueEx(hDomainKey,
|
Status = SampRegSetValue(hDomainKey,
|
||||||
L"F",
|
L"F",
|
||||||
0,
|
|
||||||
REG_BINARY,
|
REG_BINARY,
|
||||||
(LPVOID)&FixedData,
|
(LPVOID)&FixedData,
|
||||||
sizeof(SAM_DOMAIN_FIXED_DATA)))
|
sizeof(SAM_DOMAIN_FIXED_DATA));
|
||||||
return FALSE;
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
|
|
||||||
if (lpDomainSid != NULL)
|
if (lpDomainSid != NULL)
|
||||||
{
|
{
|
||||||
RegSetValueEx(hDomainKey,
|
Status = SampRegSetValue(hDomainKey,
|
||||||
L"Name",
|
L"Name",
|
||||||
0,
|
|
||||||
REG_SZ,
|
REG_SZ,
|
||||||
(LPVOID)lpDomainName,
|
(LPVOID)lpDomainName,
|
||||||
(wcslen(lpDomainName) + 1) * sizeof(WCHAR));
|
(wcslen(lpDomainName) + 1) * sizeof(WCHAR));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
|
|
||||||
RegSetValueEx(hDomainKey,
|
Status = SampRegSetValue(hDomainKey,
|
||||||
L"SID",
|
L"SID",
|
||||||
0,
|
|
||||||
REG_BINARY,
|
REG_BINARY,
|
||||||
(LPVOID)lpDomainSid,
|
(LPVOID)lpDomainSid,
|
||||||
RtlLengthSid(lpDomainSid));
|
RtlLengthSid(lpDomainSid));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
RegSetValueEx(hDomainKey,
|
Status = SampRegSetValue(hDomainKey,
|
||||||
L"OemInformation",
|
L"OemInformation",
|
||||||
0,
|
|
||||||
REG_SZ,
|
REG_SZ,
|
||||||
(LPVOID)lpEmptyString,
|
(LPVOID)lpEmptyString,
|
||||||
sizeof(WCHAR));
|
sizeof(WCHAR));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
|
|
||||||
RegSetValueEx(hDomainKey,
|
Status = SampRegSetValue(hDomainKey,
|
||||||
L"ReplicaSourceNodeName",
|
L"ReplicaSourceNodeName",
|
||||||
0,
|
|
||||||
REG_SZ,
|
REG_SZ,
|
||||||
(LPVOID)lpEmptyString,
|
(LPVOID)lpEmptyString,
|
||||||
sizeof(WCHAR));
|
sizeof(WCHAR));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
|
|
||||||
/* Create the Alias container */
|
/* Create the Alias container */
|
||||||
if (!RegCreateKeyExW(hDomainKey,
|
Status = SampRegCreateKey(hDomainKey,
|
||||||
L"Aliases",
|
L"Aliases",
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
REG_OPTION_NON_VOLATILE,
|
|
||||||
KEY_ALL_ACCESS,
|
KEY_ALL_ACCESS,
|
||||||
NULL,
|
&hAliasesKey);
|
||||||
&hAliasesKey,
|
if (!NT_SUCCESS(Status))
|
||||||
&dwDisposition))
|
goto done;
|
||||||
{
|
|
||||||
if (!RegCreateKeyExW(hAliasesKey,
|
|
||||||
L"Names",
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
REG_OPTION_NON_VOLATILE,
|
|
||||||
KEY_ALL_ACCESS,
|
|
||||||
NULL,
|
|
||||||
&hNamesKey,
|
|
||||||
&dwDisposition))
|
|
||||||
RegCloseKey(hNamesKey);
|
|
||||||
|
|
||||||
RegCloseKey(hAliasesKey);
|
Status = SampRegCreateKey(hAliasesKey,
|
||||||
}
|
L"Names",
|
||||||
|
KEY_ALL_ACCESS,
|
||||||
|
&hNamesKey);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
SampRegCloseKey(hNamesKey);
|
||||||
|
|
||||||
/* Create the Groups container */
|
/* Create the Groups container */
|
||||||
if (!RegCreateKeyExW(hDomainKey,
|
Status = SampRegCreateKey(hDomainKey,
|
||||||
L"Groups",
|
L"Groups",
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
REG_OPTION_NON_VOLATILE,
|
|
||||||
KEY_ALL_ACCESS,
|
KEY_ALL_ACCESS,
|
||||||
NULL,
|
&hGroupsKey);
|
||||||
&hGroupsKey,
|
if (!NT_SUCCESS(Status))
|
||||||
&dwDisposition))
|
goto done;
|
||||||
{
|
|
||||||
if (!RegCreateKeyExW(hGroupsKey,
|
Status = SampRegCreateKey(hGroupsKey,
|
||||||
L"Names",
|
L"Names",
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
REG_OPTION_NON_VOLATILE,
|
|
||||||
KEY_ALL_ACCESS,
|
KEY_ALL_ACCESS,
|
||||||
NULL,
|
&hNamesKey);
|
||||||
&hNamesKey,
|
if (!NT_SUCCESS(Status))
|
||||||
&dwDisposition))
|
goto done;
|
||||||
RegCloseKey(hNamesKey);
|
|
||||||
|
|
||||||
RegCloseKey(hGroupsKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
SampRegCloseKey(hNamesKey);
|
||||||
|
|
||||||
/* Create the Users container */
|
/* Create the Users container */
|
||||||
if (!RegCreateKeyExW(hDomainKey,
|
Status = SampRegCreateKey(hDomainKey,
|
||||||
L"Users",
|
L"Users",
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
REG_OPTION_NON_VOLATILE,
|
|
||||||
KEY_ALL_ACCESS,
|
KEY_ALL_ACCESS,
|
||||||
NULL,
|
&hUsersKey);
|
||||||
&hUsersKey,
|
if (!NT_SUCCESS(Status))
|
||||||
&dwDisposition))
|
goto done;
|
||||||
{
|
|
||||||
if (!RegCreateKeyExW(hUsersKey,
|
|
||||||
L"Names",
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
REG_OPTION_NON_VOLATILE,
|
|
||||||
KEY_ALL_ACCESS,
|
|
||||||
NULL,
|
|
||||||
&hNamesKey,
|
|
||||||
&dwDisposition))
|
|
||||||
RegCloseKey(hNamesKey);
|
|
||||||
|
|
||||||
RegCloseKey(hUsersKey);
|
Status = SampRegCreateKey(hUsersKey,
|
||||||
}
|
L"Names",
|
||||||
|
KEY_ALL_ACCESS,
|
||||||
|
&hNamesKey);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
SampRegCloseKey(hNamesKey);
|
||||||
|
|
||||||
if (lpDomainKey != NULL)
|
if (lpDomainKey != NULL)
|
||||||
*lpDomainKey = hDomainKey;
|
*lpDomainKey = hDomainKey;
|
||||||
|
|
||||||
return TRUE;
|
done:
|
||||||
|
if (hAliasesKey != NULL)
|
||||||
|
SampRegCloseKey(hAliasesKey);
|
||||||
|
|
||||||
|
if (hGroupsKey != NULL)
|
||||||
|
SampRegCloseKey(hGroupsKey);
|
||||||
|
|
||||||
|
if (hUsersKey != NULL)
|
||||||
|
SampRegCloseKey(hUsersKey);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
if (hDomainKey != NULL)
|
||||||
|
SampRegCloseKey(hDomainKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
SampSetupCreateServer(IN HANDLE hSamKey,
|
||||||
|
OUT HANDLE *lpServerKey)
|
||||||
|
{
|
||||||
|
HANDLE hServerKey = NULL;
|
||||||
|
HANDLE hDomainsKey = NULL;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
Status = SampRegCreateKey(hSamKey,
|
||||||
|
L"SAM",
|
||||||
|
KEY_ALL_ACCESS,
|
||||||
|
&hServerKey);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
return Status;
|
||||||
|
|
||||||
|
Status = SampRegCreateKey(hServerKey,
|
||||||
|
L"Domains",
|
||||||
|
KEY_ALL_ACCESS,
|
||||||
|
&hDomainsKey);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
SampRegCloseKey(hDomainsKey);
|
||||||
|
|
||||||
|
*lpServerKey = hServerKey;
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -724,10 +784,10 @@ BOOL
|
||||||
SampInitializeSAM(VOID)
|
SampInitializeSAM(VOID)
|
||||||
{
|
{
|
||||||
PPOLICY_ACCOUNT_DOMAIN_INFO AccountDomainInfo = NULL;
|
PPOLICY_ACCOUNT_DOMAIN_INFO AccountDomainInfo = NULL;
|
||||||
DWORD dwDisposition;
|
HANDLE hSamKey = NULL;
|
||||||
HKEY hSamKey = NULL;
|
HANDLE hServerKey = NULL;
|
||||||
HKEY hDomainsKey = NULL;
|
HANDLE hBuiltinDomainKey = NULL;
|
||||||
HKEY hDomainKey = NULL;
|
HANDLE hAccountDomainKey = NULL;
|
||||||
PSID pBuiltinSid = NULL;
|
PSID pBuiltinSid = NULL;
|
||||||
BOOL bResult = TRUE;
|
BOOL bResult = TRUE;
|
||||||
PSID pSid;
|
PSID pSid;
|
||||||
|
@ -740,38 +800,26 @@ SampInitializeSAM(VOID)
|
||||||
|
|
||||||
hInstance = GetModuleHandleW(L"samsrv.dll");
|
hInstance = GetModuleHandleW(L"samsrv.dll");
|
||||||
|
|
||||||
if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
|
/* Open the SAM key */
|
||||||
L"SAM\\SAM",
|
Status = SampRegOpenKey(NULL,
|
||||||
0,
|
L"\\Registry\\Machine\\SAM",
|
||||||
NULL,
|
KEY_READ | KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS,
|
||||||
REG_OPTION_NON_VOLATILE,
|
&hSamKey);
|
||||||
KEY_ALL_ACCESS,
|
if (!NT_SUCCESS(Status))
|
||||||
NULL,
|
|
||||||
&hSamKey,
|
|
||||||
&dwDisposition))
|
|
||||||
{
|
{
|
||||||
ERR("Failed to create 'Sam' key! (Error %lu)\n", GetLastError());
|
ERR("Failed to open the SAM key (Status: 0x%08lx)\n", Status);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RegCreateKeyExW(hSamKey,
|
/* Create the SAM Server object */
|
||||||
L"Domains",
|
Status = SampSetupCreateServer(hSamKey,
|
||||||
0,
|
&hServerKey);
|
||||||
NULL,
|
if (!NT_SUCCESS(Status))
|
||||||
REG_OPTION_NON_VOLATILE,
|
|
||||||
KEY_ALL_ACCESS,
|
|
||||||
NULL,
|
|
||||||
&hDomainsKey,
|
|
||||||
&dwDisposition))
|
|
||||||
{
|
{
|
||||||
ERR("Failed to create 'Domains' key! (Error %lu)\n", GetLastError());
|
|
||||||
bResult = FALSE;
|
bResult = FALSE;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
RegCloseKey(hSamKey);
|
|
||||||
hSamKey = NULL;
|
|
||||||
|
|
||||||
/* Create and initialize the Builtin Domain SID */
|
/* Create and initialize the Builtin Domain SID */
|
||||||
pBuiltinSid = RtlAllocateHeap(RtlGetProcessHeap(), 0, RtlLengthRequiredSid(1));
|
pBuiltinSid = RtlAllocateHeap(RtlGetProcessHeap(), 0, RtlLengthRequiredSid(1));
|
||||||
if (pBuiltinSid == NULL)
|
if (pBuiltinSid == NULL)
|
||||||
|
@ -796,16 +844,21 @@ SampInitializeSAM(VOID)
|
||||||
SampLoadString(hInstance, IDS_DOMAIN_BUILTIN_NAME, szName, 80);
|
SampLoadString(hInstance, IDS_DOMAIN_BUILTIN_NAME, szName, 80);
|
||||||
|
|
||||||
/* Create the Builtin domain */
|
/* Create the Builtin domain */
|
||||||
if (SampSetupCreateDomain(hDomainsKey,
|
Status = SampSetupCreateDomain(hServerKey,
|
||||||
L"Builtin",
|
L"Builtin",
|
||||||
szName,
|
szName,
|
||||||
pBuiltinSid,
|
pBuiltinSid,
|
||||||
&hDomainKey))
|
&hBuiltinDomainKey);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
bResult = FALSE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
SampLoadString(hInstance, IDS_ALIAS_ADMINISTRATORS_NAME, szName, 80);
|
SampLoadString(hInstance, IDS_ALIAS_ADMINISTRATORS_NAME, szName, 80);
|
||||||
SampLoadString(hInstance, IDS_ALIAS_ADMINISTRATORS_COMMENT, szComment, 256);
|
SampLoadString(hInstance, IDS_ALIAS_ADMINISTRATORS_COMMENT, szComment, 256);
|
||||||
|
|
||||||
SampSetupCreateAliasAccount(hDomainKey,
|
SampSetupCreateAliasAccount(hBuiltinDomainKey,
|
||||||
szName,
|
szName,
|
||||||
szComment,
|
szComment,
|
||||||
DOMAIN_ALIAS_RID_ADMINS);
|
DOMAIN_ALIAS_RID_ADMINS);
|
||||||
|
@ -813,7 +866,7 @@ SampInitializeSAM(VOID)
|
||||||
SampLoadString(hInstance, IDS_ALIAS_USERS_NAME, szName, 80);
|
SampLoadString(hInstance, IDS_ALIAS_USERS_NAME, szName, 80);
|
||||||
SampLoadString(hInstance, IDS_ALIAS_USERS_COMMENT, szComment, 256);
|
SampLoadString(hInstance, IDS_ALIAS_USERS_COMMENT, szComment, 256);
|
||||||
|
|
||||||
SampSetupCreateAliasAccount(hDomainKey,
|
SampSetupCreateAliasAccount(hBuiltinDomainKey,
|
||||||
szName,
|
szName,
|
||||||
szComment,
|
szComment,
|
||||||
DOMAIN_ALIAS_RID_USERS);
|
DOMAIN_ALIAS_RID_USERS);
|
||||||
|
@ -821,7 +874,7 @@ SampInitializeSAM(VOID)
|
||||||
SampLoadString(hInstance, IDS_ALIAS_GUESTS_NAME, szName, 80);
|
SampLoadString(hInstance, IDS_ALIAS_GUESTS_NAME, szName, 80);
|
||||||
SampLoadString(hInstance, IDS_ALIAS_GUESTS_COMMENT, szComment, 256);
|
SampLoadString(hInstance, IDS_ALIAS_GUESTS_COMMENT, szComment, 256);
|
||||||
|
|
||||||
SampSetupCreateAliasAccount(hDomainKey,
|
SampSetupCreateAliasAccount(hBuiltinDomainKey,
|
||||||
szName,
|
szName,
|
||||||
szComment,
|
szComment,
|
||||||
DOMAIN_ALIAS_RID_GUESTS);
|
DOMAIN_ALIAS_RID_GUESTS);
|
||||||
|
@ -829,7 +882,7 @@ SampInitializeSAM(VOID)
|
||||||
SampLoadString(hInstance, IDS_ALIAS_POWER_USERS_NAME, szName, 80);
|
SampLoadString(hInstance, IDS_ALIAS_POWER_USERS_NAME, szName, 80);
|
||||||
SampLoadString(hInstance, IDS_ALIAS_POWER_USERS_COMMENT, szComment, 256);
|
SampLoadString(hInstance, IDS_ALIAS_POWER_USERS_COMMENT, szComment, 256);
|
||||||
|
|
||||||
SampSetupCreateAliasAccount(hDomainKey,
|
SampSetupCreateAliasAccount(hBuiltinDomainKey,
|
||||||
szName,
|
szName,
|
||||||
szComment,
|
szComment,
|
||||||
DOMAIN_ALIAS_RID_POWER_USERS);
|
DOMAIN_ALIAS_RID_POWER_USERS);
|
||||||
|
@ -839,7 +892,7 @@ SampInitializeSAM(VOID)
|
||||||
DOMAIN_USER_RID_ADMIN);
|
DOMAIN_USER_RID_ADMIN);
|
||||||
if (pSid != NULL)
|
if (pSid != NULL)
|
||||||
{
|
{
|
||||||
SampSetupAddMemberToAlias(hDomainKey,
|
SampSetupAddMemberToAlias(hBuiltinDomainKey,
|
||||||
DOMAIN_ALIAS_RID_ADMINS,
|
DOMAIN_ALIAS_RID_ADMINS,
|
||||||
pSid);
|
pSid);
|
||||||
|
|
||||||
|
@ -851,27 +904,30 @@ SampInitializeSAM(VOID)
|
||||||
DOMAIN_USER_RID_GUEST);
|
DOMAIN_USER_RID_GUEST);
|
||||||
if (pSid != NULL)
|
if (pSid != NULL)
|
||||||
{
|
{
|
||||||
SampSetupAddMemberToAlias(hDomainKey,
|
SampSetupAddMemberToAlias(hBuiltinDomainKey,
|
||||||
DOMAIN_ALIAS_RID_GUESTS,
|
DOMAIN_ALIAS_RID_GUESTS,
|
||||||
pSid);
|
pSid);
|
||||||
|
|
||||||
RtlFreeHeap(RtlGetProcessHeap(), 0, pSid);
|
RtlFreeHeap(RtlGetProcessHeap(), 0, pSid);
|
||||||
}
|
}
|
||||||
|
|
||||||
RegCloseKey(hDomainKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create the Account domain */
|
/* Create the Account domain */
|
||||||
if (SampSetupCreateDomain(hDomainsKey,
|
Status = SampSetupCreateDomain(hServerKey,
|
||||||
L"Account",
|
L"Account",
|
||||||
L"",
|
L"",
|
||||||
AccountDomainInfo->DomainSid,
|
AccountDomainInfo->DomainSid,
|
||||||
&hDomainKey))
|
&hAccountDomainKey);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
bResult = FALSE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
SampLoadString(hInstance, IDS_GROUP_NONE_NAME, szName, 80);
|
SampLoadString(hInstance, IDS_GROUP_NONE_NAME, szName, 80);
|
||||||
SampLoadString(hInstance, IDS_GROUP_NONE_COMMENT, szComment, 256);
|
SampLoadString(hInstance, IDS_GROUP_NONE_COMMENT, szComment, 256);
|
||||||
|
|
||||||
SampSetupCreateGroupAccount(hDomainKey,
|
SampSetupCreateGroupAccount(hAccountDomainKey,
|
||||||
szName,
|
szName,
|
||||||
szComment,
|
szComment,
|
||||||
DOMAIN_GROUP_RID_USERS);
|
DOMAIN_GROUP_RID_USERS);
|
||||||
|
@ -879,32 +935,29 @@ SampInitializeSAM(VOID)
|
||||||
SampLoadString(hInstance, IDS_USER_ADMINISTRATOR_NAME, szName, 80);
|
SampLoadString(hInstance, IDS_USER_ADMINISTRATOR_NAME, szName, 80);
|
||||||
SampLoadString(hInstance, IDS_USER_ADMINISTRATOR_COMMENT, szComment, 256);
|
SampLoadString(hInstance, IDS_USER_ADMINISTRATOR_COMMENT, szComment, 256);
|
||||||
|
|
||||||
SampSetupCreateUserAccount(hDomainKey,
|
SampSetupCreateUserAccount(hAccountDomainKey,
|
||||||
szName,
|
szName,
|
||||||
szComment,
|
szComment,
|
||||||
DOMAIN_USER_RID_ADMIN,
|
DOMAIN_USER_RID_ADMIN,
|
||||||
USER_DONT_EXPIRE_PASSWORD | USER_NORMAL_ACCOUNT);
|
USER_DONT_EXPIRE_PASSWORD | USER_NORMAL_ACCOUNT);
|
||||||
|
|
||||||
SampSetupAddMemberToGroup(hDomainKey,
|
SampSetupAddMemberToGroup(hAccountDomainKey,
|
||||||
DOMAIN_GROUP_RID_USERS,
|
DOMAIN_GROUP_RID_USERS,
|
||||||
DOMAIN_USER_RID_ADMIN);
|
DOMAIN_USER_RID_ADMIN);
|
||||||
|
|
||||||
SampLoadString(hInstance, IDS_USER_GUEST_NAME, szName, 80);
|
SampLoadString(hInstance, IDS_USER_GUEST_NAME, szName, 80);
|
||||||
SampLoadString(hInstance, IDS_USER_GUEST_COMMENT, szComment, 256);
|
SampLoadString(hInstance, IDS_USER_GUEST_COMMENT, szComment, 256);
|
||||||
|
|
||||||
SampSetupCreateUserAccount(hDomainKey,
|
SampSetupCreateUserAccount(hAccountDomainKey,
|
||||||
szName,
|
szName,
|
||||||
szComment,
|
szComment,
|
||||||
DOMAIN_USER_RID_GUEST,
|
DOMAIN_USER_RID_GUEST,
|
||||||
USER_ACCOUNT_DISABLED | USER_DONT_EXPIRE_PASSWORD | USER_NORMAL_ACCOUNT);
|
USER_ACCOUNT_DISABLED | USER_DONT_EXPIRE_PASSWORD | USER_NORMAL_ACCOUNT);
|
||||||
|
|
||||||
SampSetupAddMemberToGroup(hDomainKey,
|
SampSetupAddMemberToGroup(hAccountDomainKey,
|
||||||
DOMAIN_GROUP_RID_USERS,
|
DOMAIN_GROUP_RID_USERS,
|
||||||
DOMAIN_USER_RID_GUEST);
|
DOMAIN_USER_RID_GUEST);
|
||||||
|
|
||||||
RegCloseKey(hDomainKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (AccountDomainInfo)
|
if (AccountDomainInfo)
|
||||||
LsaFreeMemory(AccountDomainInfo);
|
LsaFreeMemory(AccountDomainInfo);
|
||||||
|
@ -912,11 +965,17 @@ done:
|
||||||
if (pBuiltinSid)
|
if (pBuiltinSid)
|
||||||
RtlFreeHeap(RtlGetProcessHeap(), 0, pBuiltinSid);
|
RtlFreeHeap(RtlGetProcessHeap(), 0, pBuiltinSid);
|
||||||
|
|
||||||
if (hDomainsKey)
|
if (hAccountDomainKey != NULL)
|
||||||
RegCloseKey(hDomainsKey);
|
SampRegCloseKey(hAccountDomainKey);
|
||||||
|
|
||||||
if (hSamKey)
|
if (hBuiltinDomainKey != NULL)
|
||||||
RegCloseKey(hSamKey);
|
SampRegCloseKey(hBuiltinDomainKey);
|
||||||
|
|
||||||
|
if (hServerKey != NULL)
|
||||||
|
SampRegCloseKey(hServerKey);
|
||||||
|
|
||||||
|
if (hSamKey != NULL)
|
||||||
|
SampRegCloseKey(hSamKey);
|
||||||
|
|
||||||
TRACE("SampInitializeSAM() done\n");
|
TRACE("SampInitializeSAM() done\n");
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue