377 lines
12 KiB
C
377 lines
12 KiB
C
#include "basedll.h"
|
|
|
|
const OBJECT_STRING NickFile = CONSTANT_OBJECT_STRING(OTEXT("\\Device\\Harddisk0\\partition1\\UDATA\\NICKNAME.XBN"));
|
|
|
|
BOOL
|
|
WINAPI
|
|
XSetNicknameW(
|
|
IN LPCWSTR lpNickname,
|
|
IN BOOL fPreserveCase)
|
|
{
|
|
NTSTATUS Status;
|
|
OBJECT_ATTRIBUTES Obja;
|
|
IO_STATUS_BLOCK Iosb;
|
|
HANDLE FileHandle;
|
|
X_NICK_DB_ENTRY Nicknames[NUM_NICK_ENTRIES];
|
|
DWORD dwTitleID;
|
|
|
|
RIP_ON_NOT_TRUE("XSetNicknameW()", (NULL != lpNickname));
|
|
RIP_ON_NOT_TRUE("XSetNicknameW()", (wcslen(lpNickname) < MAX_NICKNAME));
|
|
|
|
if (L'\0' == *lpNickname)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
dwTitleID = XeImageHeader()->Certificate->TitleID;
|
|
|
|
InitializeObjectAttributes(&Obja, (POBJECT_STRING) &NickFile, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
|
|
|
//
|
|
// Attempt to open an existing nickname file
|
|
//
|
|
|
|
Status = NtCreateFile(&FileHandle,
|
|
SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE,
|
|
&Obja,
|
|
&Iosb,
|
|
NULL,
|
|
FILE_ATTRIBUTE_SYSTEM,
|
|
FILE_SHARE_READ,
|
|
FILE_OPEN,
|
|
FILE_WRITE_THROUGH | FILE_SYNCHRONOUS_IO_NONALERT);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
Status = NtReadFile(FileHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&Iosb,
|
|
Nicknames,
|
|
sizeof(Nicknames),
|
|
NULL);
|
|
|
|
if (NT_SUCCESS(Status) && (sizeof(Nicknames) != (DWORD) Iosb.Information))
|
|
{
|
|
//
|
|
// We didn't read the right number of bytes, so don't do anything with this
|
|
// data (the file will need to be recreated below)
|
|
//
|
|
Status = STATUS_END_OF_FILE;
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
WCHAR szNewNick[MAX_NICKNAME];
|
|
int i;
|
|
BOOL fNewEntry;
|
|
|
|
lstrcpynW(szNewNick, lpNickname, ARRAYSIZE(szNewNick));
|
|
|
|
//
|
|
// Look to see if this nickname/titleid combo already exists in the table
|
|
//
|
|
|
|
for (i = 0; i < ARRAYSIZE(Nicknames); i++)
|
|
{
|
|
if ((FALSE != (fNewEntry = (L'\0' == Nicknames[i].szNickname[0]))) ||
|
|
((dwTitleID == Nicknames[i].dwTitleID) &&
|
|
(0 == _wcsicmp(lpNickname, Nicknames[i].szNickname))))
|
|
{
|
|
if (!fNewEntry && !fPreserveCase)
|
|
{
|
|
//
|
|
// The title didn't want us to preserve the case passed in, so
|
|
// use the name as it was last written instead
|
|
//
|
|
|
|
lstrcpynW(szNewNick, Nicknames[i].szNickname, ARRAYSIZE(szNewNick));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (ARRAYSIZE(Nicknames) == i)
|
|
{
|
|
fNewEntry = TRUE;
|
|
}
|
|
|
|
if (!fNewEntry && (0 == i) && (0 == (wcscmp(szNewNick, Nicknames[0].szNickname))))
|
|
{
|
|
//
|
|
// No change - the most recent nickname is exactly the same, so just close the file
|
|
// and return TRUE without rewriting the exact same data.
|
|
//
|
|
|
|
NtClose(FileHandle);
|
|
return TRUE;
|
|
}
|
|
|
|
if (0 != i)
|
|
{
|
|
//
|
|
// Shift all of the entries further down the table to make room for this entry
|
|
// at the top of the table
|
|
//
|
|
|
|
RtlMoveMemory(&(Nicknames[1]),
|
|
&(Nicknames[0]),
|
|
sizeof(X_NICK_DB_ENTRY) * min(i, ARRAYSIZE(Nicknames) - 1));
|
|
}
|
|
|
|
//
|
|
// Write the new entry at the top of the table
|
|
//
|
|
|
|
Nicknames[0].dwTitleID = dwTitleID;
|
|
lstrcpynW(Nicknames[0].szNickname, szNewNick, ARRAYSIZE(Nicknames[0].szNickname));
|
|
}
|
|
else
|
|
{
|
|
NtClose(FileHandle);
|
|
}
|
|
}
|
|
else if (Status != STATUS_OBJECT_NAME_NOT_FOUND)
|
|
{
|
|
//
|
|
// The open failed for an unexpected reason - we don't want to proceed and
|
|
// overwrite a valid nickname file...
|
|
//
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
//
|
|
// Attempt to create a new nickname file
|
|
//
|
|
|
|
Status = NtCreateFile(&FileHandle,
|
|
SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE,
|
|
&Obja,
|
|
&Iosb,
|
|
NULL,
|
|
FILE_ATTRIBUTE_SYSTEM,
|
|
FILE_SHARE_READ,
|
|
FILE_OVERWRITE_IF,
|
|
FILE_WRITE_THROUGH | FILE_SYNCHRONOUS_IO_NONALERT);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
//
|
|
// Zero out the memory that we're going to write to the file
|
|
//
|
|
|
|
RtlZeroMemory(&Nicknames, sizeof(Nicknames));
|
|
|
|
//
|
|
// Write the new entry at the top of the table
|
|
//
|
|
|
|
Nicknames[0].dwTitleID = dwTitleID;
|
|
lstrcpynW(Nicknames[0].szNickname, lpNickname, ARRAYSIZE(Nicknames[0].szNickname));
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
//
|
|
// We have a valid FileHandle and Nicknames array at this point.
|
|
// It is time to write it back to disk and close the file..
|
|
//
|
|
|
|
LARGE_INTEGER liByteOffset;
|
|
|
|
liByteOffset.QuadPart = 0;
|
|
|
|
Status = NtWriteFile(FileHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&Iosb,
|
|
Nicknames,
|
|
sizeof(Nicknames),
|
|
&liByteOffset);
|
|
|
|
NtClose(FileHandle);
|
|
}
|
|
|
|
return(NT_SUCCESS(Status));
|
|
}
|
|
|
|
BOOL
|
|
GetNextNickname(
|
|
PFINDNICKNAME_HANDLE pFindNick,
|
|
LPWSTR lpNickname,
|
|
UINT uSize)
|
|
{
|
|
DWORD dwTitleID;
|
|
|
|
ASSERT(pFindNick && (FH_SIG_NICKNAME == pFindNick->dwSignature));
|
|
|
|
dwTitleID = XeImageHeader()->Certificate->TitleID;
|
|
|
|
for (; pFindNick->uCurIndex < ARRAYSIZE(pFindNick->Nicknames); (pFindNick->uCurIndex)++)
|
|
{
|
|
if ((L'\0' != pFindNick->Nicknames[pFindNick->uCurIndex].szNickname[0]) &&
|
|
(wcslen(pFindNick->Nicknames[pFindNick->uCurIndex].szNickname) < uSize) &&
|
|
(!pFindNick->fThisTitleOnly ||
|
|
(dwTitleID == pFindNick->Nicknames[pFindNick->uCurIndex].dwTitleID)))
|
|
{
|
|
BOOL fPrevMatch = FALSE;
|
|
#if DBG
|
|
//
|
|
// Always check for previous matches in the debug build
|
|
// (so we can validate that the nickfile doesn't have duplicates with
|
|
// the same title id)
|
|
//
|
|
#else // DBG
|
|
//
|
|
// If we're searching all title's, we need to check for previous matches
|
|
// so that we don't return duplicate names (the same name can appear
|
|
// many times with a different title id each time)
|
|
//
|
|
if (!pFindNick->fThisTitleOnly)
|
|
#endif // DBG
|
|
{
|
|
UINT uCompIndex;
|
|
for (uCompIndex = 0; uCompIndex < pFindNick->uCurIndex; uCompIndex++)
|
|
{
|
|
if (0 == _wcsicmp(pFindNick->Nicknames[pFindNick->uCurIndex].szNickname,
|
|
pFindNick->Nicknames[uCompIndex].szNickname))
|
|
{
|
|
fPrevMatch = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pFindNick->fThisTitleOnly || !fPrevMatch)
|
|
{
|
|
#if DBG
|
|
if (pFindNick->fThisTitleOnly && fPrevMatch)
|
|
{
|
|
XDBGERR("XAPI", "XFindNextNicknameW() found corrupt data (duplicate nicknames)");
|
|
}
|
|
#endif // DBG
|
|
wcscpy(lpNickname, pFindNick->Nicknames[pFindNick->uCurIndex].szNickname);
|
|
(pFindNick->uCurIndex)++;
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
HANDLE
|
|
WINAPI
|
|
XFindFirstNicknameW(
|
|
IN BOOL fThisTitleOnly,
|
|
OUT LPWSTR lpNickname,
|
|
IN UINT uSize)
|
|
{
|
|
NTSTATUS Status;
|
|
OBJECT_ATTRIBUTES Obja;
|
|
IO_STATUS_BLOCK Iosb;
|
|
HANDLE FileHandle;
|
|
PFINDNICKNAME_HANDLE pFindNick = NULL;
|
|
|
|
RIP_ON_NOT_TRUE("XFindFirstNicknameW()", (NULL != lpNickname));
|
|
|
|
InitializeObjectAttributes(&Obja, (POBJECT_STRING) &NickFile, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
|
|
|
//
|
|
// Attempt to open an existing nickname file
|
|
//
|
|
|
|
Status = NtCreateFile(&FileHandle,
|
|
SYNCHRONIZE | GENERIC_READ,
|
|
&Obja,
|
|
&Iosb,
|
|
NULL,
|
|
FILE_ATTRIBUTE_SYSTEM,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
FILE_OPEN,
|
|
FILE_SYNCHRONOUS_IO_NONALERT);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
pFindNick = LocalAlloc(LMEM_FIXED, sizeof(FINDNICKNAME_HANDLE));
|
|
|
|
if (pFindNick)
|
|
{
|
|
pFindNick->dwSignature = FH_SIG_NICKNAME;
|
|
pFindNick->uCurIndex = 0;
|
|
pFindNick->fThisTitleOnly = fThisTitleOnly;
|
|
|
|
Status = NtReadFile(FileHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&Iosb,
|
|
pFindNick->Nicknames,
|
|
sizeof(pFindNick->Nicknames),
|
|
NULL);
|
|
|
|
if (NT_SUCCESS(Status) && (sizeof(pFindNick->Nicknames) != (DWORD) Iosb.Information))
|
|
{
|
|
//
|
|
// We didn't read the right number of bytes, so don't do anything with this
|
|
// data (the file will need to be recreated below)
|
|
//
|
|
Status = STATUS_END_OF_FILE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
NtClose(FileHandle);
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
if (!GetNextNickname(pFindNick, lpNickname, uSize))
|
|
{
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status) && (NULL != pFindNick))
|
|
{
|
|
LocalFree(pFindNick);
|
|
pFindNick = NULL;
|
|
}
|
|
|
|
return (HANDLE) (pFindNick ? pFindNick : INVALID_HANDLE_VALUE);
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
XFindNextNicknameW(
|
|
IN HANDLE hFindNickname,
|
|
OUT LPWSTR lpNickname,
|
|
IN UINT uSize)
|
|
{
|
|
PFINDNICKNAME_HANDLE pFindNick = (PFINDNICKNAME_HANDLE) hFindNickname;
|
|
|
|
RIP_ON_NOT_TRUE("XFindNextNicknameW()", (NULL != hFindNickname));
|
|
RIP_ON_NOT_TRUE("XFindNextNicknameW()", (INVALID_HANDLE_VALUE != hFindNickname));
|
|
RIP_ON_NOT_TRUE("XFindNextNicknameW()", (NULL != lpNickname));
|
|
|
|
#if DBG
|
|
if (FH_SIG_NICKNAME != pFindNick->dwSignature)
|
|
{
|
|
RIP("XFindNextNicknameW() - invalid parameter (hFindNickname)");
|
|
}
|
|
#endif // DBG
|
|
|
|
return GetNextNickname(pFindNick, lpNickname, uSize);
|
|
}
|
|
|
|
|