Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1032 lines
24 KiB

/********************************************************************/
/** Copyright(c) 1989 Microsoft Corporation. **/
/********************************************************************/
//***
//
// Filename: testit
//
// Description: create and delete the network trash folder
//
// History:
// 08/06/92 SueA
// 09/16/92 JameelH Adapated to generate id database from disk
//
#include <stdio.h>
#include <stdlib.h>
#include <afp.h>
#include <pathmap.h>
#include <fdparm.h>
#include <afpinfo.h>
#include <nt.h>
// #define DBG_PRINT
#define DOSDEVICES_W L"\\DOSDEVICES\\"
#define IDDB_STREAMNAME L":Afp_IdIndex"
HANDLE hNWT, hVolRoot, hIdDb;
WCHAR VolRootName[256] = DOSDEVICES_W;
FORKOFFST Zero = { 0, 0 };
UNICODE_STRING Dot, DotDot;
PDFENTRY pDfeHashTable[IDINDEX_BUCKETS];
LONG FileEntries = 0;
LONG DirEntries = 0;
int level = -1;
DWORD gNumRead = 0, gNumWritten = 0;
#define ENUMBUF_SIZE 4096
typedef PDFENTRY (*WALKDIR_WORKER)(HANDLE hRelative, PWCHAR Name, \
ULONG Namelen, BOOLEAN IsDir,
PDFENTRY pDfeParent);
extern
DWORD
QueryCurrentTime(
VOID
);
NTSTATUS
AfpWalkDirectoryTree(
IN HANDLE hTargetDir,
IN WALKDIR_WORKER NodeWorker,
IN PDFENTRY pDfeParent
);
NTSTATUS
MyOpenFile(
LPWSTR FileName,
HANDLE hRelative,
ULONG DesiredAccess,
ULONG ShareMode,
ULONG OpenOptions,
PHANDLE phFile
);
NTSTATUS
MyCreateFile(
LPWSTR FileName,
HANDLE hRelative,
ULONG DesiredAccess,
ULONG ShareMode,
ULONG CreateOptions,
ULONG FileAttributes,
ULONG Disposition,
PHANDLE phFile,
PULONG pInformation
);
PDFENTRY
ReadIdEntry(
IN HANDLE hRelative,
IN PWCHAR Name,
IN ULONG Namelen,
IN BOOLEAN IsDir,
IN PDFENTRY pDfeParent
);
NTSTATUS
afpReadIdDbFromDisk(
IN PVOLDESC pVolDesc
);
#ifdef DBG_PRINT
#define DPRINT(_x_) printf _x_
void
indent(void);
#else
#define DPRINT(_x_)
#define indent()
#endif
VOID _cdecl
main( int argc, char*argv[] )
{
NTSTATUS Status;
PDFENTRY pDfEntry;
DWORD ElapsedTime, crinfo;
if (argc != 2)
{
printf("Usage: Scan <Full Path to volume root>\n");
return;
}
RtlInitUnicodeString(&Dot,L".");
RtlInitUnicodeString(&DotDot,L"..");
#if 1
mbstowcs((LPWSTR)((PBYTE)VolRootName+sizeof(DOSDEVICES_W)-sizeof(WCHAR)),
argv[1], sizeof(VolRootName) - sizeof(DOSDEVICES_W));
#else
mbstowcs((LPWSTR)((PBYTE)VolRootName+sizeof(DOSDEVICES_W)-sizeof(WCHAR)),
"E:\\DingBats" , sizeof(VolRootName) - sizeof(DOSDEVICES_W));
#endif
ElapsedTime = QueryCurrentTime();
DPRINT(("Opening Root Directory\n"));
Status = MyOpenFile(VolRootName,
NULL,
FILEIO_ACCESS_READ,
FILEIO_DENY_NONE,
FILEIO_OPEN_DIR_BY_NAME,
&hVolRoot);
if (NT_SUCCESS(Status))
{
pDfEntry = ReadIdEntry(hVolRoot, NULL, 0, 1, NULL);
if (pDfEntry != NULL)
Status = AfpWalkDirectoryTree(hVolRoot, ReadIdEntry, pDfEntry);
// NtClose(hVolRoot);
ElapsedTime = QueryCurrentTime() - ElapsedTime;
if (!NT_SUCCESS(Status))
printf("Failure to read in all entries %lx\n", Status);
printf("Total number of entries read %ld files, %ld directories, Time %ld seconds\n",
FileEntries, DirEntries, ElapsedTime/1000);
}
else printf("Root directory %s Open Error %lx\n", argv[1], Status);
Status = MyCreateFile(IDDB_STREAMNAME,hVolRoot,FILEIO_ACCESS_READWRITE,
FILEIO_DENY_NONE, FILEIO_OPEN_FILE_BY_NAME,
FILE_ATTRIBUTE_NORMAL,FILE_OPEN_IF,&hIdDb,&crinfo);
if (NT_SUCCESS(Status))
{
printf("Writing out IdDb to stream...\n");
ElapsedTime = QueryCurrentTime();
AfpUpdateIdDb(NULL);
ElapsedTime = QueryCurrentTime() - ElapsedTime;
printf("Total number entries written: %ld\n",gNumWritten);
printf("Elapsed time for Writing the IdDb stream: %ld seconds.\n",
ElapsedTime/1000);
AfpFreeIdIndexTables(NULL);
printf("Reading Id Database stream on volume root...\n");
ElapsedTime = QueryCurrentTime();
afpReadIdDbFromDisk(NULL);
ElapsedTime = QueryCurrentTime() - ElapsedTime;
printf("Total number read: %ld\n",gNumRead);
printf("Elapsed time for Reading the IdDb stream: %ld seconds.\n",
ElapsedTime/1000);
}
else printf("Error creating IdDb stream on volume root (0x%lx)\n",Status);
}
PDFENTRY
ReadIdEntry(
IN HANDLE hRelative,
IN PWCHAR Name,
IN ULONG Namelen,
IN BOOLEAN IsDir,
IN PDFENTRY pDfeParent
)
{
int i;
HANDLE hEntity = NULL;
NTSTATUS rc = STATUS_INSUFFICIENT_RESOURCES;
WCHAR wnamesz[60];
IO_STATUS_BLOCK iosb;
AFPINFO AfpInfo;
PDFENTRY pDfEntry;
UNICODE_STRING UName;
RtlMoveMemory(wnamesz, Name, Namelen);
RtlMoveMemory((PBYTE)wnamesz+Namelen,
L":AFP_AfpInfo", sizeof(L":AFP_Afp_Info"));
UName.Length = (USHORT)Namelen;
UName.MaximumLength = (USHORT)(Namelen+sizeof(WCHAR));
UName.Buffer = Name;
do
{
if ((pDfEntry = (PDFENTRY)malloc(sizeof(DFENTRY) +
Namelen/sizeof(WCHAR) + 1)) == NULL)
{
printf("Allocation of DFENTRY Failed\n");
break;
}
pDfEntry->dfe_Name.Buffer = (PBYTE)pDfEntry + sizeof(DFENTRY);
pDfEntry->dfe_Name.Length = (USHORT)(Namelen/sizeof(WCHAR));
pDfEntry->dfe_Name.MaximumLength = (USHORT)(Namelen/sizeof(WCHAR)+1);
RtlUnicodeStringToAnsiString(&pDfEntry->dfe_Name, &UName, False);
rc = MyOpenFile(wnamesz,
hRelative,
FILEIO_ACCESS_READ,
FILEIO_DENY_NONE,
FILEIO_OPEN_FILE_BY_NAME,
&hEntity);
if (!NT_SUCCESS(rc))
{
printf("Failed to open AfpInfo stream for %s <%lx>\n",
pDfEntry->dfe_Name.Buffer, rc);
break;
}
rc = NtReadFile(hEntity, NULL, NULL, NULL, &iosb, &AfpInfo,
sizeof(AfpInfo), &Zero, 0);
if (!NT_SUCCESS(rc))
{
printf("Failed to read in AfpInfo stream for %s <%lx>\n",
pDfEntry->dfe_Name.Buffer, rc);
break;
}
rc = NtQueryInformationFile(hEntity, &iosb,
&pDfEntry->dfe_Id.dfi_FsId, sizeof(FILE_INTERNAL_INFORMATION),
FileInternalInformation);
if (!NT_SUCCESS(rc))
{
printf("Failed to get FsId for %s <%lx>\n",
pDfEntry->dfe_Name.Buffer, rc);
break;
}
pDfEntry->dfe_Id.dfi_AfpId = AfpInfo.afpi_Id;
pDfEntry->dfe_Flags = IsDir ? DFE_FLAGS_DIR : DFE_FLAGS_FILE_NO_ID;
i = HASH_ID(pDfEntry->dfe_Id.dfi_AfpId);
pDfEntry->dfe_Overflow = pDfeHashTable[i];
pDfeHashTable[i] = pDfEntry;
pDfEntry->dfe_Parent = pDfeParent;
pDfEntry->dfe_Sibling = (pDfeParent != NULL) ? pDfeParent->dfe_Child : NULL;
if ((pDfeParent != NULL))
pDfeParent->dfe_Child = pDfEntry;
pDfEntry->dfe_Child = NULL;
if (IsDir)
DirEntries ++;
else FileEntries ++;
} while (False);
if (!NT_SUCCESS(rc))
{
if (pDfEntry != NULL)
free (pDfEntry);
}
if (hEntity != NULL)
NtClose(hEntity);
return(pDfEntry);
}
NTSTATUS
MyOpenFile(
LPWSTR FileName,
HANDLE hRelative,
ULONG DesiredAccess,
ULONG ShareMode,
ULONG OpenOptions,
PHANDLE phFile
)
{
OBJECT_ATTRIBUTES objattr;
IO_STATUS_BLOCK iosb;
UNICODE_STRING fname;
NTSTATUS rc;
RtlInitUnicodeString(&fname,FileName);
InitializeObjectAttributes(&objattr,
&fname,
OBJ_CASE_INSENSITIVE,
hRelative,
NULL);
rc = NtOpenFile( phFile,
DesiredAccess,
&objattr,
&iosb,
ShareMode,
OpenOptions);
return(rc);
}
NTSTATUS
MyQueryDirectoryFile(
IN HANDLE DirHandle,
OUT PFILE_DIRECTORY_INFORMATION Enumbuf,
IN ULONG Enumbuflen,
IN BOOLEAN ReturnSingleEntry,
IN BOOLEAN RestartScan
)
{
NTSTATUS rc;
IO_STATUS_BLOCK iosb;
rc = NtQueryDirectoryFile(DirHandle,
NULL,NULL,NULL,
&iosb,
Enumbuf,
Enumbuflen,
FileDirectoryInformation,
ReturnSingleEntry,
NULL,
RestartScan);
return(rc);
}
NTSTATUS
AfpGetNextDirectoryInfo(
IN OUT PFILE_DIRECTORY_INFORMATION *ppInfoBuf,
OUT PWCHAR *pNodeName,
OUT PULONG pNodeNameLen,
OUT PBOOLEAN pIsDir
)
{
PFILE_DIRECTORY_INFORMATION tempdirinfo;
if (*ppInfoBuf == NULL)
{
return(STATUS_NO_MORE_ENTRIES);
}
tempdirinfo = *ppInfoBuf;
if (tempdirinfo->NextEntryOffset == 0)
{
*ppInfoBuf = NULL;
}
else
{
(PBYTE)*ppInfoBuf += tempdirinfo->NextEntryOffset;
}
*pIsDir = (tempdirinfo->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ?
True : False;
*pNodeNameLen = tempdirinfo->FileNameLength;
*pNodeName = tempdirinfo->FileName;
return(STATUS_SUCCESS);
}
NTSTATUS
AfpWalkDirectoryTree(
IN HANDLE hTargetDir,
IN WALKDIR_WORKER NodeWorker,
IN PDFENTRY pDfeParent
)
{
PFILE_DIRECTORY_INFORMATION pDirInfo;
NTSTATUS Status = STATUS_SUCCESS;
PBYTE enumbuf;
PWCHAR nodename;
ULONG nodenamelen;
BOOLEAN isdir;
UNICODE_STRING udirname;
HANDLE hChildDir;
PDFENTRY pDfEntry;
level ++;
//
// allocate the buffer that will hold enumerated files and dirs
//
if ((enumbuf = (PBYTE) malloc(ENUMBUF_SIZE)) == NULL)
{
printf("Allocation of enum buffer failed\n");
Status = STATUS_INSUFFICIENT_RESOURCES;
}
else do // error handling loop
{
//
// keep enumerating till we get all the entries
//
while (True)
{
Status = MyQueryDirectoryFile(hTargetDir,
(PFILE_DIRECTORY_INFORMATION)enumbuf,
ENUMBUF_SIZE,
False, // dont return single entry
False);
ASSERT(Status != STATUS_PENDING);
if ((Status == STATUS_NO_MORE_FILES) ||
(Status == STATUS_NO_SUCH_FILE) ||
(Status == STATUS_NO_MORE_ENTRIES))
{
Status = STATUS_SUCCESS;
break; // that's it, we've seen everything there is
}
//
// NOTE: if we get STATUS_BUFFER_OVERFLOW, the IO Status
// information field does NOT tell us the required size
// of the buffer, so we wouldn't know how big to realloc
// the enum buffer if we wanted to retry, so don't bother
else if (!NT_SUCCESS(Status))
{
printf("Enumerate failed\n");
break; // enumerate failed, bail out
}
//
// process the enumerated files and dirs
// NOTE: for test purposes we will just ask for single
// entries for now from QueryDirectoryFile
//
pDirInfo = (PFILE_DIRECTORY_INFORMATION)enumbuf;
while (True)
{
if ((Status = AfpGetNextDirectoryInfo(&pDirInfo,
&nodename,
&nodenamelen,
&isdir)) == STATUS_NO_MORE_ENTRIES)
{
Status = STATUS_SUCCESS;
break;
}
if (isdir == True)
{
udirname.Buffer = nodename;
udirname.Length = (USHORT)nodenamelen;
udirname.MaximumLength = (USHORT)nodenamelen;
if (RtlEqualUnicodeString(&Dot,&udirname,True) ||
RtlEqualUnicodeString(&DotDot,&udirname,True))
continue;
}
//
// call worker with its relative handle and path
//
if ((pDfEntry = NodeWorker(hTargetDir,
nodename,
nodenamelen,
isdir,
pDfeParent)) == NULL)
{
Status = STATUS_UNSUCCESSFUL;
break;
}
// If it is a directory we'll recurse
if (isdir == True)
{
WCHAR temp[32];
AfpInitUnicodeStringWithNonNullTerm(&udirname,
(USHORT)nodenamelen, nodename);
if (RtlEqualUnicodeString(&Dot,&udirname,True) ||
RtlEqualUnicodeString(&DotDot,&udirname,True))
{
continue;
}
RtlMoveMemory(temp, nodename, nodenamelen);
temp[nodenamelen/sizeof(WCHAR)] = 0;
indent(); DPRINT(("Opening Directory %ws\n", temp));
//
// get a handle to the directory to recurse
//
Status = MyOpenFile(temp,
hTargetDir,
FILEIO_ACCESS_READ,
FILEIO_DENY_NONE,
FILEIO_OPEN_DIR_BY_NAME,
&hChildDir);
if (!NT_SUCCESS(Status))
{
DPRINT(("Unable to open Directory %ws\n", temp));
break;
}
Status = AfpWalkDirectoryTree(hChildDir, NodeWorker, pDfEntry);
NtClose(hChildDir);
indent();DPRINT(("Closing Directory %ws\n", nodename));
if (!NT_SUCCESS(Status))
break;
}
} // while more entries in the enumbuf
if (!NT_SUCCESS(Status))
break;
} // while there are more files to enumerate
free(enumbuf);
} while (False); // error handling loop
level --;
return(Status);
}
#ifdef DBG_PRINT
void
indent()
{
int i;
for (i = 0; i < level; i++)
printf("\t");
}
#endif
VOID
AfpUpdateIdDb(
IN PVOLDESC pVolDesc
)
{
PBYTE pWriteBuf;
NTSTATUS Status;
IDDBHDR IdDbHdr;
BOOLEAN WriteEntireHdr = False;
PDFENTRY pCurDfe;
DWORD SizeLeft; // the number of free bytes left in the writebuffer
DWORD CurEntSize, NumWritten = 0;
DWORD Offset;
PDFDISKENTRY pCurDiskEnt;
IO_STATUS_BLOCK iosb;
LARGE_INTEGER liOffset;
if ((pWriteBuf = (PBYTE)malloc(IDDB_UPDATE_BUFLEN)) == NULL)
{
printf("Error allocating a write buffer\n");
return;
}
SizeLeft = IDDB_UPDATE_BUFLEN;
pCurDiskEnt = (PDFDISKENTRY)pWriteBuf;
// write out a count of zero first
IdDbHdr.idh_Signature = AFP_SERVER_SIGNATURE;
IdDbHdr.idh_Version = AFP_SERVER_VERSION;
IdDbHdr.idh_LastId = AFP_ID_NETWORK_TRASH;
// AfpGetCurrentTimeInMacFormat(&CurrentTime);
IdDbHdr.idh_CreateTime = 0; //CurrentTime;
IdDbHdr.idh_ModifiedTime = 0; //CurrentTime;
IdDbHdr.idh_BackupTime = BEGINNING_OF_TIME;
IdDbHdr.idh_Count = 0;
Offset = 0;
liOffset = RtlConvertUlongToLargeInteger(Offset);
Status = NtWriteFile(hIdDb, NULL, NULL, NULL, &iosb, &IdDbHdr,
sizeof(IdDbHdr), &liOffset, NULL);
// start with the root (don't write out the parent of root)
for (pCurDfe = pDfeHashTable[HASH_ID(AFP_ID_ROOT)];
(pCurDfe != NULL) && (pCurDfe->dfe_Id.dfi_AfpId >= AFP_ID_ROOT);
pCurDfe = pCurDfe->dfe_Overflow)
{
if (pCurDfe->dfe_Id.dfi_AfpId == AFP_ID_ROOT)
break;
}
// pCurDfe = AfpFindEntryByAfpId(NULL,AFP_ID_ROOT,DFE_DIR);
ASSERT((pCurDfe != NULL) && (pCurDfe->dfe_Sibling == NULL));
Offset = sizeof(IdDbHdr);
do
{
CurEntSize = sizeof(DFDISKENTRY) + pCurDfe->dfe_Name.Length +
DWPAD(pCurDfe->dfe_Name.Length);
if (CurEntSize > SizeLeft)
{
// write out the buffer and start at the beginning of buffer
liOffset = RtlConvertUlongToLargeInteger(Offset);
//printf("About to write stream at offset %ld...\n",Offset);
Status = NtWriteFile(hIdDb, NULL, NULL, NULL, &iosb, pWriteBuf,
IDDB_UPDATE_BUFLEN - SizeLeft, &liOffset, NULL);
if (!NT_SUCCESS(Status))
{
printf("Error writing IdDb stream (0x%lx)\n",Status);
free(pWriteBuf);
return;
}
Offset += (IDDB_UPDATE_BUFLEN - SizeLeft);
SizeLeft = IDDB_UPDATE_BUFLEN;
pCurDiskEnt = (PDFDISKENTRY)pWriteBuf;
}
// stick the current entry into the write buffer
NumWritten ++;
pCurDiskEnt->dsk_AfpId = pCurDfe->dfe_Id.dfi_AfpId;
pCurDiskEnt->dsk_HostId = pCurDfe->dfe_Id.dfi_FsId;
pCurDiskEnt->dsk_Flags = pCurDfe->dfe_Flags & DFE_FLAGS_DFBITS;
pCurDiskEnt->dsk_Signature = AFP_DFDISKENTRY_SIGNATURE;
if (pCurDfe->dfe_Child != NULL)
{
if (!DFE_IS_NWTRASH(pCurDfe->dfe_Child) ||
(DFE_IS_NWTRASH(pCurDfe->dfe_Child) &&
(pCurDfe->dfe_Child->dfe_Sibling != NULL)))
{
pCurDiskEnt->dsk_Flags |= DFE_FLAGS_HAS_CHILD;
}
}
if (pCurDfe->dfe_Sibling != NULL)
{
if (!DFE_IS_NWTRASH(pCurDfe->dfe_Sibling) ||
(DFE_IS_NWTRASH(pCurDfe->dfe_Sibling) &&
(pCurDfe->dfe_Sibling->dfe_Sibling != NULL)))
{
pCurDiskEnt->dsk_Flags |= DFE_FLAGS_HAS_SIBLING;
}
}
pCurDiskEnt->dsk_Flags |= pCurDfe->dfe_Name.Length;
RtlMoveMemory((PBYTE)pCurDiskEnt + sizeof(DFDISKENTRY),
pCurDfe->dfe_Name.Buffer,
pCurDfe->dfe_Name.Length);
SizeLeft -= CurEntSize;
pCurDiskEnt = (PDFDISKENTRY)((PBYTE)pCurDiskEnt + CurEntSize);
if (pCurDfe->dfe_Child != NULL)
{
pCurDfe = pCurDfe->dfe_Child;
// don't bother writing out the network trash tree
if (DFE_IS_NWTRASH(pCurDfe))
{
// could be null, if so, we're done
pCurDfe = pCurDfe->dfe_Sibling;
}
}
else if (pCurDfe->dfe_Sibling != NULL)
{
pCurDfe = pCurDfe->dfe_Sibling;
}
else if (DFE_IS_ROOT(pCurDfe))
break;
else
{
while (pCurDfe->dfe_Parent->dfe_Sibling == NULL)
{
if (DFE_IS_ROOT(pCurDfe->dfe_Parent))
{
break;
}
pCurDfe = pCurDfe->dfe_Parent;
}
pCurDfe = pCurDfe->dfe_Parent->dfe_Sibling; // if ROOT then you get NULL
}
} while (pCurDfe != NULL);
if (SizeLeft < IDDB_UPDATE_BUFLEN)
{
// write out the last of the entries
liOffset = RtlConvertUlongToLargeInteger(Offset);
Status = NtWriteFile(hIdDb, NULL, NULL, NULL, &iosb, pWriteBuf,
IDDB_UPDATE_BUFLEN - SizeLeft, &liOffset, NULL);
if (!NT_SUCCESS(Status))
{
printf("Error writing IdDb stream (0x%lx)\n",Status);
free(pWriteBuf);
return;
}
}
#if 0
// set the file to length of IdDb plus header
AfpIoSetSize(& hIdDb,Offset + (IDDB_UPDATE_BUFLEN - SizeLeft));
#endif
// free the pWriteBuf
free(pWriteBuf);
#if 0
// now write out the actual count of entities written to the file
if ((pVolDesc->vds_Flags & VOLUME_IDDBHDR_DIRTY) &&
!(pVolDesc->vds_Flags & VOLUME_IDDBHDR_FLUSH_QUEUED))
{
// Snapshot the IdDbHdr
IdDbHdr = pVolDesc->vds_IdDbHdr;
WriteEntireHdr = True;
}
else
{
// BUGBUG do we really need to take the lock to get the count? since
// nobody could get in to add/delete anything cuz we have the swmr lock!
ASSERT(NumWritten == (pVolDesc->vds_IdDbHdr.idh_Count - 1));
Count = pVolDesc->vds_IdDbHdr.idh_Count;
}
pVolDesc->vds_cChangesIdDb = 0;
pVolDesc->vds_cScvgrIdDb = 0;
#endif
// write out the count
IdDbHdr.idh_Count = NumWritten;
Offset = 0;
liOffset = RtlConvertUlongToLargeInteger(Offset);
Status = NtWriteFile(hIdDb, NULL, NULL, NULL, &iosb, &IdDbHdr,
sizeof(IdDbHdr), &liOffset, NULL);
gNumWritten = NumWritten;
}
NTSTATUS
afpReadIdDbFromDisk(
IN PVOLDESC pVolDesc
)
{
IDDBHDR IdDbHdr;
PBYTE pReadBuf;
NTSTATUS Status;
DWORD Offset = 0, NumRead = 0, CurEntSize;
DWORD SizeRead = 0, SizeLeft = 0;
PDFENTRY pCurParentDfe = NULL, pCurDfe = NULL;
ANSI_STRING aName;
BOOLEAN LastBuf = False;
PDFDISKENTRY pCurDiskEnt;
IO_STATUS_BLOCK iosb;
LARGE_INTEGER liOffset;
// read in the header
liOffset = RtlConvertUlongToLargeInteger(Offset);
Status = NtReadFile(hIdDb, NULL, NULL, NULL, &iosb, (PBYTE)&IdDbHdr,
sizeof(IDDBHDR), &liOffset, NULL );
SizeRead = iosb.Information;
if (!NT_SUCCESS(Status) || (SizeRead != sizeof(IdDbHdr)) ||
(IdDbHdr.idh_Signature != AFP_SERVER_SIGNATURE) ||
(IdDbHdr.idh_Version != AFP_SERVER_VERSION) ||
(IdDbHdr.idh_Count == 0) || (IdDbHdr.idh_LastId < AFP_ID_NETWORK_TRASH))
{
printf("Error in IdDb Header\n");
return(STATUS_UNSUCCESSFUL);
}
if ((pReadBuf = malloc(IDDB_UPDATE_BUFLEN)) == NULL)
{
return(STATUS_NO_MEMORY);
}
//
// seed the database with the PARENT_OF_ROOT
//
if ((pCurParentDfe = (PDFENTRY)malloc(sizeof(DFENTRY)))== NULL)
{
free(pReadBuf);
return(STATUS_NO_MEMORY);
}
pCurParentDfe->dfe_Name.Buffer = NULL;
pCurParentDfe->dfe_Name.Length = pCurParentDfe->dfe_Name.MaximumLength = 0;
pCurParentDfe->dfe_Flags = DFE_FLAGS_DIR;
pCurParentDfe->dfe_DirDepth = -1;
pCurParentDfe->dfe_Overflow = NULL;
pCurParentDfe->dfe_Parent = NULL;
pCurParentDfe->dfe_Child = NULL;
pCurParentDfe->dfe_Sibling = NULL;
pCurParentDfe->dfe_Id.dfi_AfpId = AFP_ID_PARENT_OF_ROOT;
pCurParentDfe->dfe_Id.dfi_FsId.HighPart = 0;
pCurParentDfe->dfe_Id.dfi_FsId.LowPart = 0;
// link it into the hash buckets
pDfeHashTable[HASH_ID(AFP_ID_PARENT_OF_ROOT)] = pCurParentDfe;
//
// start reading the entries from disk
//
Offset = sizeof(IdDbHdr);
while (NumRead < IdDbHdr.idh_Count)
{
//
// get the next entry
//
// are we left with a partial entry, or no more entries in buffer?
CheckForPartialEntry:
if ((SizeLeft < sizeof(DFDISKENTRY)) ||
(SizeLeft < (CurEntSize = sizeof(DFDISKENTRY) +
(DWORD)(pCurDiskEnt->dsk_Flags & DFE_FLAGS_NAMELENBITS) +
DWPAD((DWORD)(pCurDiskEnt->dsk_Flags & DFE_FLAGS_NAMELENBITS)))))
{
if (LastBuf) // we have already read to the end of file
{
Status = STATUS_UNSUCCESSFUL;
break;
}
// backup (if necessary) and re-read the next entry
Offset -= SizeLeft;
liOffset = RtlConvertUlongToLargeInteger(Offset);
Status = NtReadFile(hIdDb, NULL, NULL, NULL, &iosb, pReadBuf,
IDDB_UPDATE_BUFLEN, &liOffset, NULL);
if (!NT_SUCCESS(Status))
{
printf("Error reading from IdDb stream at offset 0x%lx (rc=0x%lx)\n",
Offset,Status);
break;
}
SizeRead = iosb.Information;
Offset += SizeRead;
// if we read less than we asked for, then we reached EOF
LastBuf = SizeRead < IDDB_UPDATE_BUFLEN;
SizeLeft = SizeRead;
pCurDiskEnt = (PDFDISKENTRY)pReadBuf;
goto CheckForPartialEntry;
}
//
// check dsk_Reserved for signature, just to be sure you are
// still aligned on a structure and not off in la-la land
//
if (pCurDiskEnt->dsk_Signature != AFP_DFDISKENTRY_SIGNATURE)
{
printf("DFDiskEntry signature is bad\n");
Status = STATUS_UNSUCCESSFUL;
break;
}
// add current entry to database
aName.Buffer = (PCHAR)pCurDiskEnt + sizeof(DFDISKENTRY);
aName.Length =
aName.MaximumLength = pCurDiskEnt->dsk_Flags & DFE_FLAGS_NAMELENBITS;
if ((pCurDfe = AfpAddIdEntry(pVolDesc, pCurParentDfe, &aName,
pCurDiskEnt->dsk_HostId,
(pCurDiskEnt->dsk_Flags & DFE_FLAGS_DIR)?True:False,
pCurDiskEnt->dsk_AfpId)) == NULL)
{
Status = STATUS_UNSUCCESSFUL;
break;
}
pCurDfe->dfe_Flags |= pCurDiskEnt->dsk_Flags & DFE_FLAGS_CSENCODEDBITS;
NumRead ++;
SizeLeft -= CurEntSize;
pCurDiskEnt = (PDFDISKENTRY)((PBYTE)pCurDiskEnt + CurEntSize);
//
// figure out who the next parent should be
//
if (pCurDfe->dfe_Flags & DFE_FLAGS_HAS_CHILD)
{
pCurParentDfe = pCurDfe;
}
else if (!(pCurDfe->dfe_Flags & DFE_FLAGS_HAS_SIBLING))
{
if (DFE_IS_PARENT_OF_ROOT(pCurParentDfe))
{
ASSERT(NumRead == IdDbHdr.idh_Count);
break;
}
while (!(pCurParentDfe->dfe_Flags & DFE_FLAGS_HAS_SIBLING))
{
if (DFE_IS_ROOT(pCurParentDfe))
{
break;
}
pCurParentDfe = pCurParentDfe->dfe_Parent;
}
pCurParentDfe = pCurParentDfe->dfe_Parent;
if (DFE_IS_PARENT_OF_ROOT(pCurParentDfe))
{
ASSERT(NumRead == IdDbHdr.idh_Count);
break;
}
}
} // while
#if 0
if (!NT_SUCCESS(Status))
{
AfpFreeIdIndexTables(pVolDesc);
}
#endif
free(pReadBuf);
gNumRead = NumRead; // set global so don't printf here
return(Status);
}
NTSTATUS
MyCreateFile(
LPWSTR FileName,
HANDLE hRelative,
ULONG DesiredAccess,
ULONG ShareMode,
ULONG CreateOptions,
ULONG FileAttributes,
ULONG Disposition,
PHANDLE phFile,
PULONG pInformation
)
{
OBJECT_ATTRIBUTES objattr;
IO_STATUS_BLOCK iosb;
UNICODE_STRING fname;
NTSTATUS rc;
RtlInitUnicodeString(&fname,FileName);
InitializeObjectAttributes(&objattr,
&fname,
OBJ_CASE_INSENSITIVE,
hRelative,
NULL);
// printf("about to call NtCreateFile on %ws\n",fname.Buffer);
rc = NtCreateFile(phFile,
DesiredAccess,
&objattr,
&iosb,
0,
FileAttributes,
ShareMode,
Disposition,
CreateOptions,
NULL,0);
*pInformation = iosb.Information;
// printf("NtCreateFile returned 0x%lx (information=0x%lx)\n",rc,*pInformation);
return(rc);
}
PDFENTRY
AfpAddIdEntry(
IN PVOLDESC pVolDesc,
IN PDFENTRY pDfeParent,
IN PANSI_STRING Name,
IN HOSTID FsId,
IN BOOLEAN Directory,
IN DWORD AfpId OPTIONAL
)
{
PDFENTRY pDfEntry, *ppDfEntry;
ASSERT(DFE_IS_DIRECTORY(pDfeParent));
if ((pDfEntry = (PDFENTRY)malloc(sizeof(DFENTRY) + Name->Length)) == NULL)
return(NULL);
pDfEntry->dfe_Id.dfi_AfpId = AfpId;
pDfEntry->dfe_Id.dfi_FsId = FsId;
AfpSetEmptyAnsiString(&pDfEntry->dfe_Name,Name->Length,
(PBYTE)pDfEntry+sizeof(DFENTRY));
RtlCopyString(&pDfEntry->dfe_Name,Name);
if (Directory)
{
DFE_SET_DIRECTORY(pDfEntry, pDfeParent->dfe_DirDepth);
}
else
{
DFE_SET_FILE(pDfEntry);
}
// link it into the database
pDfEntry->dfe_Parent = pDfeParent;
pDfEntry->dfe_Sibling = pDfeParent->dfe_Child;
pDfeParent->dfe_Child = pDfEntry;
pDfEntry->dfe_Child = NULL;
// Now link this into the hash bucket, sorted in AFP Id descending order
ppDfEntry = &(pDfeHashTable[HASH_ID(AfpId)]);
while (*ppDfEntry != NULL)
{
if (pDfEntry->dfe_Id.dfi_AfpId > (*ppDfEntry)->dfe_Id.dfi_AfpId)
{
break;
}
ppDfEntry = &((*ppDfEntry)->dfe_Overflow);
}
pDfEntry->dfe_Overflow = *ppDfEntry;
*ppDfEntry = pDfEntry;
return (pDfEntry);
}
VOID
AfpFreeIdIndexTables(
IN PVOLDESC pVolDesc
)
{
LONG i;
printf("Freeing the Hash Table entries...\n");
// Traverse each of the hashed indices and free the entries.
// Need only traverse the overflow links. Ignore other links.
for (i = 0; i < IDINDEX_BUCKETS; i++)
{
PDFENTRY pDfEntry, pFree;
for (pDfEntry = pDfeHashTable[i]; pDfEntry != NULL; )
{
pFree = pDfEntry;
pDfEntry = pDfEntry->dfe_Overflow;
free(pFree);
}
pDfeHashTable[i] = NULL;
}
}