
/**
 * @file: object_initializer.c
 *
 * tento soubor je soucasti frameworku na prochazeni internich datovych struktur 
 * spravce objektu v jadre Windows. V tomto souboru jsou implementovany rutiny na praci
 * se strukturou OBJECT_TYPE_INITIALIZER znamou tez jako "Object Initializer."
 */
#include <ntddk.h>
#include "version.h"
#include "driver.h"
#include "object_header.h"
#include "object_initializer.h"

// Cislo verze operacniho systemu, na ktere ovaldac prave bezi
static ULONG VersionCode = VERSION_UNKNOWN;



/** Zjisti ruzne priznaky definovane pro dany typ objektu.
 *
 * Rutina zjistuje nasledujici priznaky:
 *   CaseInsensitive: spravce objektu nebere ohled na velikost pismen pri praci s danymi objekty
 *   MaintainHandleCount: kazdy objekt daneho typu obsahuje hlavicku OBJECT_HEADER_HANDLE_INFO.
 *   MaintainTypeList: Vsechny objekty daneho typu jsou propojeny cyklickym spojovym seznamem.
 *   SecurityRequired: Kazdy objekt daneho druhu vyzaduje popisovac zabezpeceni.
 *   SupportsObjectCallbacks: Tento typ objektu je podporovan OB filtering modelem.
 *   UnnamedObjectsOnly: Objekty tohoto druhu nemohou mit jmeno.
 *   UseDefaultObject: Umoznit cekat na objekty daneho druhu pomoci objektu dispatcher.
 *
 * @param Initializer Adresa struktury OBJECT_TYPE_INITIALIZER ciloveho typu objektu.
 * @param Flags Adresa struktury OBJECT_INITIALIZER_FLAGS, ktera v pripade uspechu obdrzi
 * priznaky daneho typu objektu.
 *
 * @return Funkce vraci hodnotu NTSTATU indikujici uspech ci neuspech operace.
 */
NTSTATUS OTIGetFlags(PVOID Initializer, POBJECT_INITIALIZER_FLAGS Flags)
{
  NTSTATUS Status = STATUS_UNSUCCESSFUL;
  KdPrint(("object_initializer.c: OTIGetFlags(Initializer=0x%p; Flags=0x%p)\n", Initializer, Flags));

  Status = STATUS_SUCCESS;
  RtlZeroMemory(Flags, sizeof(OBJECT_INITIALIZER_FLAGS));
  switch (VersionCode) {
    case VERSION_W2K:
	  Flags->CaseInsensitive = 1;
	  Flags->MaintainHandleCount = OTIW2KMaintainHandleCount(Initializer);
	  Flags->MaintainTypeList = OTIW2KMaintainTypeList(Initializer);
	  Flags->SecurityRequired = OTIW2KSecurityRequired(Initializer);
	  Flags->SupportsObjectCallbacks = 0;
	  Flags->UnnamedObjectsOnly = 0;
	  Flags->UseDefaultObject = OTIW2KUseDefaultObject(Initializer);
      break;

    case VERSION_WXP:
	  Flags->CaseInsensitive = OTIWXPCaseInsensitive(Initializer);
	  Flags->MaintainHandleCount = OTIWXPMaintainHandleCount(Initializer);
	  Flags->MaintainTypeList = OTIWXPMaintainTypeList(Initializer);
	  Flags->SecurityRequired = OTIWXPSecurityRequired(Initializer);
	  Flags->SupportsObjectCallbacks = 0;
	  Flags->UnnamedObjectsOnly = 0;
	  Flags->UseDefaultObject = OTIWXPUseDefaultObject(Initializer);
      break;

    case VERSION_W2K3:
	  Flags->CaseInsensitive = OTIW2K3CaseInsensitive(Initializer);
	  Flags->MaintainHandleCount = OTIW2K3MaintainHandleCount(Initializer);
	  Flags->MaintainTypeList = OTIW2K3MaintainTypeList(Initializer);
	  Flags->SecurityRequired = OTIW2K3SecurityRequired(Initializer);
	  Flags->SupportsObjectCallbacks = 0;
	  Flags->UnnamedObjectsOnly = 0;
	  Flags->UseDefaultObject = OTIW2K3UseDefaultObject(Initializer);
      break;
  
    case VERSION_VISTA:
	  Flags->CaseInsensitive = OTIVistaCaseInsensitive(Initializer);
	  Flags->MaintainHandleCount = OTIVistaMaintainHandleCount(Initializer);
	  Flags->MaintainTypeList = OTIVistaMaintainTypeList(Initializer);
	  Flags->SecurityRequired = OTIVistaSecurityRequired(Initializer);
	  Flags->SupportsObjectCallbacks = OTIVistaSupportsObjectCallbacks(Initializer);
	  Flags->UnnamedObjectsOnly = OTIVistaUnnamedObjectsOnly(Initializer);
	  Flags->UseDefaultObject = OTIVistaUseDefaultObject(Initializer);
      break;

	case VERSION_W7:
	  Flags->CaseInsensitive = OTIW7CaseInsensitive(Initializer);
	  Flags->MaintainHandleCount = OTIW7MaintainHandleCount(Initializer);
	  Flags->MaintainTypeList = OTIW7MaintainTypeList(Initializer);
	  Flags->SecurityRequired = OTIW7SecurityRequired(Initializer);
	  Flags->SupportsObjectCallbacks = OTIW7SupportsObjectCallbacks(Initializer);
	  Flags->UnnamedObjectsOnly = OTIW7UnnamedObjectsOnly(Initializer);
	  Flags->UseDefaultObject = OTIW7UseDefaultObject(Initializer);
      break;
    default:
      Status = STATUS_NOT_SUPPORTED;
      KdPrint(("object_initializer.c: OTIGetFlags(): OS version not supported\n"));
      break;
  }

  KdPrint(("object_initializer.c: OTIGetFlags(-):0x%x\n", Status));
  return Status;
}


/** Zjisti adresy (virtualnich) metod pro dany typ objektu.
 *
 * @param Initializer Adresa struktury OBJECT_TYPE_INITIALIZER ciloveho objektu typu.
 * @param Methods Adresa struktury OBJECT_INITIALIZER_METHODS, kterou funkce v pripade
 * uspechu vyplni adresami jednotlivych metod prislusnych pro dany typ objektu.
 *
 * @return Funkce vraci hodnotu NTSTATUS indikujici uspech ci neuspech operace.
 */
NTSTATUS OTIGetMethods(PVOID Initializer, POBJECT_INITIALIZER_METHODS Methods)
{
  NTSTATUS Status = STATUS_UNSUCCESSFUL;
  KdPrint(("object_initializer.c: OTIGetMethods(Initializer=0x%p; Methods=0x%p)\n", Initializer, Methods));

  Status = STATUS_SUCCESS;
  RtlZeroMemory(Methods, sizeof(OBJECT_INITIALIZER_METHODS));
  switch (VersionCode) {
    case VERSION_W2K:
      Methods->Close = OTIW2KCloseProcedure(Initializer);
      Methods->Delete = OTIW2KDeleteProcedure(Initializer);
	  Methods->Dump = OTIW2KDumpProcedure(Initializer);
	  Methods->OkayToClose = OTIW2KOkayToCloseProcedure(Initializer);
	  Methods->Open = OTIW2KOpenProcedure(Initializer);
	  Methods->Parse = OTIW2KParseProcedure(Initializer);
	  Methods->QueryName = OTIW2KQueryNameProcedure(Initializer);
	  Methods->Security = OTIW2KSecurityProcedure(Initializer);
      break;

    case VERSION_WXP:
      Methods->Close = OTIWXPCloseProcedure(Initializer);
      Methods->Delete = OTIWXPDeleteProcedure(Initializer);
	  Methods->Dump = OTIWXPDumpProcedure(Initializer);
	  Methods->OkayToClose = OTIWXPOkayToCloseProcedure(Initializer);
	  Methods->Open = OTIWXPOpenProcedure(Initializer);
	  Methods->Parse = OTIWXPParseProcedure(Initializer);
	  Methods->QueryName = OTIWXPQueryNameProcedure(Initializer);
	  Methods->Security = OTIWXPSecurityProcedure(Initializer);
      break;

    case VERSION_W2K3:
      Methods->Close = OTIW2K3CloseProcedure(Initializer);
      Methods->Delete = OTIW2K3DeleteProcedure(Initializer);
	  Methods->Dump = OTIW2K3DumpProcedure(Initializer);
	  Methods->OkayToClose = OTIW2K3OkayToCloseProcedure(Initializer);
	  Methods->Open = OTIW2K3OpenProcedure(Initializer);
	  Methods->Parse = OTIW2K3ParseProcedure(Initializer);
	  Methods->QueryName = OTIW2K3QueryNameProcedure(Initializer);
	  Methods->Security = OTIW2K3SecurityProcedure(Initializer);
      break;

    case VERSION_VISTA:
      Methods->Close = OTIVistaCloseProcedure(Initializer);
      Methods->Delete = OTIVistaDeleteProcedure(Initializer);
	  Methods->Dump = OTIVistaDumpProcedure(Initializer);
	  Methods->OkayToClose = OTIVistaOkayToCloseProcedure(Initializer);
	  Methods->Open = OTIVistaOpenProcedure(Initializer);
	  Methods->Parse = OTIVistaParseProcedure(Initializer);
	  Methods->QueryName = OTIVistaQueryNameProcedure(Initializer);
	  Methods->Security = OTIVistaSecurityProcedure(Initializer);
      break;

    case VERSION_W7:
      Methods->Close = OTIW7CloseProcedure(Initializer);
      Methods->Delete = OTIW7DeleteProcedure(Initializer);
	  Methods->Dump = OTIW7DumpProcedure(Initializer);
	  Methods->OkayToClose = OTIW7OkayToCloseProcedure(Initializer);
	  Methods->Open = OTIW7OpenProcedure(Initializer);
	  Methods->Parse = OTIW7ParseProcedure(Initializer);
	  Methods->QueryName = OTIW7QueryNameProcedure(Initializer);
	  Methods->Security = OTIW7SecurityProcedure(Initializer);
      break;

    default:
      Status = STATUS_NOT_SUPPORTED;
      KdPrint(("object_initializer.c: OTIGetMethods(): OS version not supported\n"));
      break;
  }

  KdPrint(("object_initializer.c: OTIGetMethods(-):0x%x\n", Status));
  return Status;
}


/** Zjisti ruzne informace o danem typu objektu.
 *
 * Jedna se napriklad o nasledujici udaje:
 *   DefaultNonPagedPoolCharge: vychozi velikost nestrankovanou pameti odebirana pri otevreni handle z kvoty procesu.
 *   DefaultPagedPoolCharge: vychozi velikost strankovanou pameti odebirana pri otevreni handle z kvoty procesu.
 *   InvalidAttributes: Neplatne priznaky pristupovych opravneni k objektu.
 *   PoolType: Typ pametoveho fondu, ze ktereho ma spravce alokovat hlavicku a telo objektu.
 *   RetainAccess: Priznaky pristupovych prav, ktere nelze odebrat v ramci OB filtering modelu.
 *   ValidAccessMask: Platne priznaky pristupovych opravneni.
 *
 * @param Initializer Adresa struktury OBJECT_TYPE_INITIALIZER daneho objektu typu.
 * @param OtherInfo Adresa struktury OBJECT_INITIALIZER_OTHER_INFO, kterou funkce v pripade
 * uspechu vyplni ruznymi udaji o cilovem objektu typu.
 *
 * @return Funkce vraci hodnotu NTSTATUS indikujici uspech ci neuspech.
 */
NTSTATUS OTIGetOtherInfo(PVOID Initializer, POBJECT_INITIALIZER_OTHER_INFO OtherInfo)
{
  NTSTATUS Status = STATUS_UNSUCCESSFUL;
  KdPrint(("object_initializer.c: OTIGetOtherInfo(Initializer=0x%p; OtherInfo=0x%p)\n", Initializer, OtherInfo));

  Status = STATUS_SUCCESS;
  RtlZeroMemory(OtherInfo, sizeof(OBJECT_INITIALIZER_OTHER_INFO));
  switch (VersionCode) {
    case VERSION_W2K:
      OtherInfo->DefaultNonPagedPoolCharge = OTIW2KDefaultNonPagedPoolCharge(Initializer);
      OtherInfo->DefaultPagedPoolCharge = OTIW2KDefaultPagedPoolCharge(Initializer);
      OtherInfo->InvalidAttributes = OTIW2KInvalidAttributes(Initializer);
      OtherInfo->ObjectTypeCode = 0; 
	  OtherInfo->PoolType = OTIW2KPoolType(Initializer);
      OtherInfo->RetainAccess = 0;
      OtherInfo->VaildAccessMask = OTIW2KValidAccessMask(Initializer);
      break;

    case VERSION_WXP:
      OtherInfo->DefaultNonPagedPoolCharge = OTIWXPDefaultNonPagedPoolCharge(Initializer);
      OtherInfo->DefaultPagedPoolCharge = OTIWXPDefaultPagedPoolCharge(Initializer);
      OtherInfo->InvalidAttributes = OTIWXPInvalidAttributes(Initializer);
      OtherInfo->ObjectTypeCode = 0;
	  OtherInfo->PoolType = OTIWXPPoolType(Initializer);
      OtherInfo->RetainAccess = 0;
      OtherInfo->VaildAccessMask = OTIWXPValidAccessMask(Initializer);
      break;

    case VERSION_W2K3:
      OtherInfo->DefaultNonPagedPoolCharge = OTIW2K3DefaultNonPagedPoolCharge(Initializer);
      OtherInfo->DefaultPagedPoolCharge = OTIW2K3DefaultPagedPoolCharge(Initializer);
      OtherInfo->InvalidAttributes = OTIW2K3InvalidAttributes(Initializer);
      OtherInfo->ObjectTypeCode = 0;
	  OtherInfo->PoolType = OTIW2K3PoolType(Initializer);
      OtherInfo->RetainAccess = 0;
      OtherInfo->VaildAccessMask = OTIW2K3ValidAccessMask(Initializer);
      break;

    case VERSION_VISTA:
      OtherInfo->DefaultNonPagedPoolCharge = OTIVistaDefaultNonPagedPoolCharge(Initializer);
      OtherInfo->DefaultPagedPoolCharge = OTIVistaDefaultPagedPoolCharge(Initializer);
      OtherInfo->InvalidAttributes = OTIVistaInvalidAttributes(Initializer);
      OtherInfo->ObjectTypeCode = OTIVistaObjectTypeCode(Initializer);
	  OtherInfo->PoolType = OTIVistaPoolType(Initializer);
      OtherInfo->RetainAccess = OTIVistaRetainAccess(Initializer);
      OtherInfo->VaildAccessMask = OTIVistaValidAccessMask(Initializer);
      break;

    case VERSION_W7:
      OtherInfo->DefaultNonPagedPoolCharge = OTIW7DefaultNonPagedPoolCharge(Initializer);
      OtherInfo->DefaultPagedPoolCharge = OTIW7DefaultPagedPoolCharge(Initializer);
      OtherInfo->InvalidAttributes = OTIW7InvalidAttributes(Initializer);
      OtherInfo->ObjectTypeCode = OTIW7ObjectTypeCode(Initializer);
	  OtherInfo->PoolType = OTIW7PoolType(Initializer);
      OtherInfo->RetainAccess = OTIW7RetainAccess(Initializer);
      OtherInfo->VaildAccessMask = OTIW7ValidAccessMask(Initializer);
      break;

	default:
      Status = STATUS_NOT_SUPPORTED;
      KdPrint(("object_initializer.c: OTIGetOtherInfo(): OS version not supported\n"));
      break;
  }

  KdPrint(("object_initializer.c: OTIGetOtherInfo(-):0x%x\n", Status));
  return Status;
}



/** Inicializuje modul pro praci se strukturami OBJECT_TYPE_INITIALIZER.
 *
 * Rutina pouze zjisti cislo verze operacniho systemu, na ktere ovladac aktualne bezi.
 *
 * @param DriverObject Adresa struktury DRIVER_OBJECT reprezentujici aktualni ovladac.
 *
 * @return Funkce vraci hodnotu NTSTATUS indikujici uspech ci neuspech operace.
 */
NTSTATUS OTIInit(PDRIVER_OBJECT DriverObject)
{
  NTSTATUS Status = STATUS_UNSUCCESSFUL;
  KdPrint(("object_initializer.c: OTIInit(DriverObject=0x%p)\n", DriverObject));

  VersionCode = GetVersionCode();
  if (VersionCode != VERSION_UNKNOWN)
    Status = STATUS_SUCCESS;
  else Status = STATUS_NOT_SUPPORTED;

  KdPrint(("object_initializer.c: OTIInit(-):0x%x\n", Status));
  return Status;
}


/** Rutina provede uklid po modulu pro praci se strukturami OBJECT_TYPE_INITIALIZER.
 *
 * Protoze tento modul pri neprovadi zadne zasahy do struktur spravce objektu nebo jadra,
 * tatu funkce nedela nic.
 */
VOID OTIFinit(VOID)
{
  KdPrint(("object_initializer.c: OTIFinit()\n"));

  KdPrint(("object_initializer.c: OTIFinit(-)\n"));
  return;
}
