static VOID
XenPci_IoWatch(char *path, PVOID context)
{
  NTSTATUS status;
  watch_context_t *watch_context = context;
  WDFFILEOBJECT file_object = watch_context->file_object;
  PXENPCI_DEVICE_INTERFACE_DATA xpdid = GetXpdid(file_object);
  KIRQL old_irql;
  struct xsd_sockmsg *rep;
  xenbus_read_queue_item_t *list_entry;
  size_t remaining;
  WDFREQUEST request;

  FUNCTION_ENTER();
  
  KeAcquireSpinLock(&xpdid->lock, &old_irql);
  
  remaining = sizeof(struct xsd_sockmsg) + strlen(path) + 1 + strlen(watch_context->token) + 1;
  rep = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct xsd_sockmsg) + strlen(path) + 1 + strlen(watch_context->token) + 1, XENPCI_POOL_TAG);
  rep->type = XS_WATCH_EVENT;
  rep->req_id = 0;
  rep->tx_id = 0;
  rep->len = (ULONG)(strlen(path) + 1 + strlen(watch_context->token) + 1);
  remaining -= sizeof(struct xsd_sockmsg);
  RtlStringCbCopyA((PCHAR)(rep + 1), remaining, path);
  remaining -= strlen(path) + 1;
  RtlStringCbCopyA((PCHAR)(rep + 1) + strlen(path) + 1, remaining, watch_context->token);
  
  list_entry = (xenbus_read_queue_item_t *)ExAllocatePoolWithTag(NonPagedPool, sizeof(xenbus_read_queue_item_t), XENPCI_POOL_TAG);
  list_entry->data = rep;
  list_entry->length = sizeof(*rep) + rep->len;
  list_entry->offset = 0;
  InsertTailList(&xpdid->xenbus.read_list_head, (PLIST_ENTRY)list_entry);
    
  status = WdfIoQueueRetrieveNextRequest(xpdid->xenbus.io_queue, &request);
  if (NT_SUCCESS(status))
  {
    WDF_REQUEST_PARAMETERS parameters;
    WDF_REQUEST_PARAMETERS_INIT(&parameters);
    WdfRequestGetParameters(request, &parameters);
    
    KdPrint((__DRIVER_NAME "     found pending read - MinorFunction = %d, length = %d\n", (ULONG)parameters.MinorFunction, (ULONG)parameters.Parameters.Read.Length));
    XenBus_ProcessReadRequest(xpdid->xenbus.io_queue, request, parameters.Parameters.Read.Length);
    KeReleaseSpinLock(&xpdid->lock, old_irql);
    WdfRequestComplete(request, STATUS_SUCCESS);
  }
  else
  {
    KdPrint((__DRIVER_NAME "     no pending read (%08x)\n", status));
    KeReleaseSpinLock(&xpdid->lock, old_irql);
  }
  
  FUNCTION_EXIT();
}
BOOLEAN SympAddSymbol(IN PCHAR pszSymbolName, IN ULONG64 uSymbolAddress, IN ULONG uOffset, IN ULONG uBitPosition, IN ULONG uBitLength)
{
	ASSERTMSG("Cannot add symbol with NULL name", pszSymbolName != NULL);
	ASSERTMSG("SymbolEngine must be initialized prior to this call", bIsSymEngineInitialized == TRUE);

	// it is possible that we got symbol with zero address, offset -1, bit position -1, and length -1 if the symbol was not found during
	// enumeration in user mode. In that case, and only in that case, we return error!
	// NOTE: uSymbolAddress of -1 is used when symbols are initialized in order to send the array of wanted symbols to the user mode
	if(uSymbolAddress == 0 && uOffset == -1 && uBitPosition == -1 && uBitLength == -1)
	{
		KdPrint(("[DEBUG] WARNING - Symbol was probably not found in user mode, cannot add symbol with unknown address and unknown offset\n"));
		return FALSE;
	}

	// if symbol with this name already exists
	if(SympFindSymbol(pszSymbolName) != NULL)
	{
		// don't want to "update" the address -- use SymUpdateSymbol function instead
		KdPrint(("[DEBUG] WARNING - Symbol %s with address 0x%x already exists -- use SymUpdateFunction() to update the address\n", pszSymbolName, uSymbolAddress));
		return TRUE;
	}

	// get memory from lookaside list
	PSYMBOL_ENTRY pSymbolEntry = (PSYMBOL_ENTRY) ExAllocateFromNPagedLookasideList(&SymbolsLookasideList);
	if(pSymbolEntry == NULL)
	{
		KdPrint(("[DEBUG] ERROR - Not enough memory in lookaside list to allocate new symbol entry\n"));
		return FALSE;
	}

	// copy string from passed parameter
	if(RtlStringCbCopyA(pSymbolEntry->Symbol.name, MAX_SYM_NAME, pszSymbolName) == STATUS_INVALID_PARAMETER)
	{
		KdPrint(("[DEBUG] ERROR - Error while copying symbol name to SYMBOL_ENTRY structure\n"));
		return FALSE;
	}

	// copy address from the passed parameter
	pSymbolEntry->Symbol.u64address = uSymbolAddress;

	// copy offset from the passed parameter
	pSymbolEntry->Symbol.uOffset = uOffset;

	// copy bit position from the passed parameter
	pSymbolEntry->Symbol.uBitPosition = uBitPosition;

	// copy bit length from the passed parameter
	pSymbolEntry->Symbol.uBitLength = uBitLength;

	// insert it to list (thread safe)
	ASSERTMSG("Fast mutex acquire must occur at or below APC_LEVEL", KeGetCurrentIrql() <= APC_LEVEL);
	ExAcquireFastMutex(&SymbolsListMutex);
	InsertHeadList(&SymbolsListHead, &pSymbolEntry->ListEntry);
	++uSymbolCount;
	ASSERTMSG("Fast mutex release must occur at APC_LEVEL", KeGetCurrentIrql() == APC_LEVEL);
	ExReleaseFastMutex(&SymbolsListMutex);

	return TRUE;
}
Ejemplo n.º 3
0
void Insert(DWORD key, PDATA pData, PHASHTABLE pHashTable)
{
	PTWOWAY pNode = NULL; 
	PTWOWAY pNewNode = NULL;
	PLIST_ENTRY pListHead = NULL;

	pNode = Find(key, pHashTable);
	// The node with the given key was not found.
	if (pNode == NULL)
	{
		pNewNode = ExAllocateFromNPagedLookasideList(pLookasideList_TWOWAY);
		if (pNewNode == NULL)
		{
			DbgPrint("ExAllocateFromNPagedLookasideList returned NULL!\n");
			return;
		}
		
		// Insert the data to the node.
		pNewNode->key = key;
		pNewNode->data.threadID = pData->threadID;
		pNewNode->data.processID = pData->processID;
		if (STATUS_SUCCESS != RtlStringCbCopyA(pNewNode->data.imageName, 16, pData->imageName))
		{
			DbgPrint("RtlStringCbCopyA failed!\n");
		}

		// Insert the node to the doubly-linked list.
		pListHead = pHashTable->pListHeads[Hash(key, pHashTable->tableSize)];
		InsertTailList(pListHead, &pNewNode->linkfield);
#ifdef MY_DEBUG
		DbgPrint("INSERT: thread ID = 0x%x process ID = 0x%x image = %s\n", pData->threadID, pData->processID, pData->imageName);
#endif
	}
#ifdef MY_DEBUG
	else
	{
		if (pNode->data.processID != pData->processID)
		{
			DbgPrint("Node with key = 0x%x already in list\n", key);
			DbgPrint("OLD: thread ID = 0x%x process ID = 0x%x image = %s\n", pNode->data.threadID, pNode->data.processID, pNode->data.imageName);
			DbgPrint("NEW: thread ID = 0x%x process ID = 0x%x image = %s\n", pData->threadID, pData->processID, pData->imageName);
		}
	}
#endif
}
Ejemplo n.º 4
0
static NTSTATUS
XenPci_GetBackendDetails(WDFDEVICE device)
{
  PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
  PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
  char path[128];
  PCHAR res;
  PCHAR value;

  FUNCTION_ENTER();
  /* Get backend path */
  RtlStringCbPrintfA(path, ARRAY_SIZE(path),
    "%s/backend", xppdd->path);
  res = XenBus_Read(xpdd, XBT_NIL, path, &value);
  if (res)
  {
    FUNCTION_MSG("Failed to read backend path\n");
    XenPci_FreeMem(res);
    return STATUS_UNSUCCESSFUL;
  }
  RtlStringCbCopyA(xppdd->backend_path, ARRAY_SIZE(xppdd->backend_path), value);
  XenPci_FreeMem(value);

  /* Get backend id */
  RtlStringCbPrintfA(path, ARRAY_SIZE(path),
    "%s/backend-id", xppdd->path);
  res = XenBus_Read(xpdd, XBT_NIL, path, &value);
  if (res) {
    FUNCTION_MSG("Failed to read backend id\n");
    XenPci_FreeMem(res);
    return STATUS_UNSUCCESSFUL;
  }
  xppdd->backend_id = (domid_t)atoi(value);
  XenPci_FreeMem(value);
  FUNCTION_EXIT();  
  return STATUS_SUCCESS;
}
Ejemplo n.º 5
0
VOID
VIOSerialPortDeviceControl(
    IN WDFQUEUE   Queue,
    IN WDFREQUEST Request,
    IN size_t     OutputBufferLength,
    IN size_t     InputBufferLength,
    IN ULONG      IoControlCode
    )
{
    PRAWPDO_VIOSERIAL_PORT  pdoData = RawPdoSerialPortGetData(WdfIoQueueGetDevice(Queue));
    size_t                  length = 0;
    NTSTATUS                status = STATUS_SUCCESS;
    PVIRTIO_PORT_INFO       pport_info = NULL;
    size_t                  name_size = 0;

    PAGED_CODE();

    UNREFERENCED_PARAMETER( InputBufferLength  );
    UNREFERENCED_PARAMETER( OutputBufferLength  );

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "--> %s\n", __FUNCTION__);

    switch (IoControlCode)
    {

        case IOCTL_GET_INFORMATION:
        {
           status = WdfRequestRetrieveOutputBuffer(Request, sizeof(VIRTIO_PORT_INFO), (PVOID*)&pport_info, &length);
           if (!NT_SUCCESS(status))
           {
              TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS,
                            "WdfRequestRetrieveInputBuffer failed 0x%x\n", status);
              WdfRequestComplete(Request, status);
              return;
           }
           if (pdoData->port->NameString.Buffer)
           {
              name_size = pdoData->port->NameString.MaximumLength;
           }
           if (length < sizeof (VIRTIO_PORT_INFO) + name_size)
           {
              status = STATUS_BUFFER_TOO_SMALL;
              TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS,
                            "Buffer too small. get = %d, expected = %d\n", length, sizeof (VIRTIO_PORT_INFO) + name_size);
              length = sizeof (VIRTIO_PORT_INFO) + name_size;
              break;
           }
           RtlZeroMemory(pport_info, sizeof(VIRTIO_PORT_INFO));
           pport_info->Id = pdoData->port->PortId;
           pport_info->OutVqFull = pdoData->port->OutVqFull;
           pport_info->HostConnected = pdoData->port->HostConnected;
           pport_info->GuestConnected = pdoData->port->GuestConnected;

           if (pdoData->port->NameString.Buffer)
           {
              RtlZeroMemory(pport_info->Name, name_size);
              status = RtlStringCbCopyA(pport_info->Name, name_size - 1, pdoData->port->NameString.Buffer);
              if (!NT_SUCCESS(status))
              {
                 TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS,
                            "RtlStringCbCopyA failed 0x%x\n", status);
                 name_size = 0;
              }
           }
           status = STATUS_SUCCESS;
           length =  sizeof (VIRTIO_PORT_INFO) + name_size;
           break;
        }

        default:
           status = STATUS_INVALID_DEVICE_REQUEST;
           break;
    }
    WdfRequestCompleteWithInformation(Request, status, length);
    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "<-- %s\n", __FUNCTION__);
}
VOID
FxInitializeBugCheckDriverInfo()
{
    NTSTATUS                                 status;
    UNICODE_STRING                           funcName;
    PKBUGCHECK_REASON_CALLBACK_RECORD        callbackRecord;
    PFN_KE_REGISTER_BUGCHECK_REASON_CALLBACK funcPtr;
    SIZE_T                                   arraySize;
    ULONG                                    arrayCount;
    

    callbackRecord = &FxLibraryGlobals.BugCheckCallbackRecord;
    RtlZeroMemory(callbackRecord, sizeof(KBUGCHECK_REASON_CALLBACK_RECORD));

    FxLibraryGlobals.BugCheckDriverInfoCount = 0;
    FxLibraryGlobals.BugCheckDriverInfoIndex = 0;
    FxLibraryGlobals.BugCheckDriverInfo = NULL;











    // The KeRegisterBugCheckReasonCallback exists for xp sp1 and above. So
    // check whether this function is defined on the current OS and register
    // for the bugcheck callback only if this function is defined.
    //
    RtlInitUnicodeString(&funcName, L"KeRegisterBugCheckReasonCallback");
    funcPtr = (PFN_KE_REGISTER_BUGCHECK_REASON_CALLBACK)
        MmGetSystemRoutineAddress(&funcName);

    if (NULL == funcPtr) {
        goto Done;
    }

    arraySize = sizeof(FX_DUMP_DRIVER_INFO_ENTRY) * FX_DUMP_DRIVER_INFO_INCREMENT;
    arrayCount = FX_DUMP_DRIVER_INFO_INCREMENT;

    FxLibraryGlobals.BugCheckDriverInfo = 
        (PFX_DUMP_DRIVER_INFO_ENTRY)MxMemory::MxAllocatePoolWithTag(
                                    NonPagedPool,
                                    arraySize,
                                    FX_TAG);
    
    if (NULL == FxLibraryGlobals.BugCheckDriverInfo) {
        goto Done;
    }

    FxLibraryGlobals.BugCheckDriverInfoCount = arrayCount;
    
    //
    // Init first entry for the framework.
    //
    FxLibraryGlobals.BugCheckDriverInfo[0].FxDriverGlobals = NULL;
    FxLibraryGlobals.BugCheckDriverInfo[0].Version.Major = __WDF_MAJOR_VERSION;
    FxLibraryGlobals.BugCheckDriverInfo[0].Version.Minor = __WDF_MINOR_VERSION;
    FxLibraryGlobals.BugCheckDriverInfo[0].Version.Build = __WDF_BUILD_NUMBER;
    
    status = RtlStringCbCopyA(
                    FxLibraryGlobals.BugCheckDriverInfo[0].DriverName,
                    sizeof(FxLibraryGlobals.BugCheckDriverInfo[0].DriverName),
                    WdfLdrType);
    
    if (!NT_SUCCESS(status)) {
        ASSERT(FALSE);
        FxLibraryGlobals.BugCheckDriverInfo[0].DriverName[0] = '\0';     
    }

    FxLibraryGlobals.BugCheckDriverInfoIndex++;

    //
    // Initialize the callback record.
    //
    KeInitializeCallbackRecord(callbackRecord);

    //
    // Register the bugcheck callback.
    //
    funcPtr(callbackRecord,
            FxpLibraryBugCheckCallback,
            KbCallbackSecondaryDumpData,
            (PUCHAR)WdfLdrType);

    ASSERT(callbackRecord->CallbackRoutine != NULL);

Done:;
}
Ejemplo n.º 7
0
static ULONG
XenScsi_HwScsiFindAdapter(PVOID DeviceExtension, PVOID Reserved1, PVOID Reserved2, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PUCHAR Reserved3)
{
  ULONG i;
  PXENSCSI_DEVICE_DATA xsdd = DeviceExtension;
  PACCESS_RANGE access_range;
  PUCHAR ptr;
  USHORT type;
  PCHAR setting, value, value2;
  vscsiif_sring_t *sring;
  CHAR path[128];

  UNREFERENCED_PARAMETER(Reserved1);
  UNREFERENCED_PARAMETER(Reserved2);
  UNREFERENCED_PARAMETER(ArgumentString);
  UNREFERENCED_PARAMETER(Reserved3);

  FUNCTION_ENTER();
  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
  
  xsdd->scsiport_paused = TRUE; /* wait for initial scan */

  KdPrint((__DRIVER_NAME "     BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
  KdPrint((__DRIVER_NAME "     BusInterruptVector = %03x\n", ConfigInfo->BusInterruptVector));

  if (!ConfigInfo->BusInterruptVector)
  {
    KdPrint((__DRIVER_NAME "     No Interrupt assigned\n"));
    return SP_RETURN_BAD_CONFIG;
  }

  if (ConfigInfo->NumberOfAccessRanges != 1)
  {
    KdPrint((__DRIVER_NAME "     NumberOfAccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));
    return SP_RETURN_BAD_CONFIG;
  }

  ptr = NULL;
  access_range = &((*(ConfigInfo->AccessRanges))[0]);
  KdPrint((__DRIVER_NAME "     RangeStart = %08x, RangeLength = %08x\n",
    access_range->RangeStart.LowPart, access_range->RangeLength));
  ptr = ScsiPortGetDeviceBase(
    DeviceExtension,
    ConfigInfo->AdapterInterfaceType,
    ConfigInfo->SystemIoBusNumber,
    access_range->RangeStart,
    access_range->RangeLength,
    !access_range->RangeInMemory);
  if (!ptr)
  {
    KdPrint((__DRIVER_NAME "     Unable to map range\n"));
    KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));  
    return SP_RETURN_BAD_CONFIG;
  }
  sring = NULL;
  xsdd->event_channel = 0;
  while((type = GET_XEN_INIT_RSP(&ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
  {
    switch(type)
    {
    case XEN_INIT_TYPE_RING: /* frontend ring */
      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
      if (strcmp(setting, "ring-ref") == 0)
      {
        sring = (vscsiif_sring_t *)value;
        FRONT_RING_INIT(&xsdd->ring, sring, PAGE_SIZE);
      }
      break;
    //case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
    case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel */
      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, PtrToUlong(value)));
      if (strcmp(setting, "event-channel") == 0)
      {
        xsdd->event_channel = PtrToUlong(value);
      }
      break;
    case XEN_INIT_TYPE_READ_STRING_BACK:
    case XEN_INIT_TYPE_READ_STRING_FRONT:
      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
      break;
    case XEN_INIT_TYPE_VECTORS:
      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_VECTORS\n"));
      if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
        ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
      {
        KdPrint((__DRIVER_NAME "     vectors mismatch (magic = %08x, length = %d)\n",
          ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
        KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
        return SP_RETURN_BAD_CONFIG;
      }
      else
        memcpy(&xsdd->vectors, value, sizeof(XENPCI_VECTORS));
      break;
    case XEN_INIT_TYPE_GRANT_ENTRIES:
      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(value)));
      xsdd->grant_entries = (USHORT)PtrToUlong(value);
      memcpy(&xsdd->grant_free_list, value2, sizeof(grant_ref_t) * xsdd->grant_entries);
      xsdd->grant_free = xsdd->grant_entries;
      break;
    default:
      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_%d\n", type));
      break;
    }
  }

  if (sring == NULL || xsdd->event_channel == 0)
  {
    KdPrint((__DRIVER_NAME "     Missing settings\n"));
    KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    return SP_RETURN_BAD_CONFIG;
  }
  
  ConfigInfo->ScatterGather = TRUE;
  ConfigInfo->NumberOfPhysicalBreaks = VSCSIIF_SG_TABLESIZE - 1;
  ConfigInfo->MaximumTransferLength = VSCSIIF_SG_TABLESIZE * PAGE_SIZE;
  ConfigInfo->CachesData = FALSE;
  ConfigInfo->NumberOfBuses = 4; //SCSI_MAXIMUM_BUSES; //8
  ConfigInfo->MaximumNumberOfTargets = 16;
  ConfigInfo->MaximumNumberOfLogicalUnits = SCSI_MAXIMUM_LOGICAL_UNITS; // 8
  ConfigInfo->BufferAccessScsiPortControlled = TRUE;
  if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
  {
    ConfigInfo->Master = TRUE;
    ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
    KdPrint((__DRIVER_NAME "     Dma64BitAddresses supported\n"));
  }
  else
  {
    ConfigInfo->Master = FALSE;
    KdPrint((__DRIVER_NAME "     Dma64BitAddresses not supported\n"));
  }
  ConfigInfo->InitiatorBusId[0] = 7;
  ConfigInfo->InitiatorBusId[1] = 7;
  ConfigInfo->InitiatorBusId[2] = 7;
  ConfigInfo->InitiatorBusId[3] = 7;
  xsdd->shadow_free = 0;
  memset(xsdd->shadows, 0, sizeof(vscsiif_shadow_t) * SHADOW_ENTRIES);
  for (i = 0; i < SHADOW_ENTRIES; i++)
  {
    xsdd->shadows[i].req.rqid = (USHORT)i;
    put_shadow_on_freelist(xsdd, &xsdd->shadows[i]);
  }

  if (!dump_mode)
  {
    InitializeListHead(&xsdd->dev_list_head);
    /* should do something if we haven't enumerated in a certain time */
    RtlStringCbCopyA(path, ARRAY_SIZE(path), xsdd->vectors.backend_path);
    RtlStringCbCatA(path, ARRAY_SIZE(path), "/vscsi-devs");
    xsdd->vectors.XenBus_AddWatch(xsdd->vectors.context, XBT_NIL, path,
      XenScsi_DevWatch, xsdd);
  }
  FUNCTION_EXIT();

  return SP_RETURN_FOUND;
}
Ejemplo n.º 8
0
/* If Initialize fails then the watch still gets called but the waits will never be acked... */
static VOID
XenScsi_DevWatch(PCHAR path, PVOID DeviceExtension)
{
  PXENSCSI_DEVICE_DATA xsdd = DeviceExtension;
  CHAR tmp_path[128];
  PCHAR msg;
  PCHAR *devices;
  PCHAR value;
  scsi_dev_t *dev;
  ULONG i;
  ULONG dev_no;
  ULONG state;
  LARGE_INTEGER wait_time;
  #if DBG
  ULONG oldpause;
  #endif

  UNREFERENCED_PARAMETER(path);
  
  /* this can only be called from a watch and so is always serialised */
  FUNCTION_ENTER();

  #if DBG
  oldpause =
  #endif
    InterlockedExchange(&xsdd->shared_paused, SHARED_PAUSED_PASSIVE_PAUSED);
  ASSERT(oldpause == SHARED_PAUSED_SCSIPORT_UNPAUSED);
  
  while (InterlockedCompareExchange(&xsdd->shared_paused, SHARED_PAUSED_SCSIPORT_PAUSED, SHARED_PAUSED_SCSIPORT_PAUSED) != SHARED_PAUSED_SCSIPORT_PAUSED)
  {
    KdPrint((__DRIVER_NAME "     Waiting for pause...\n"));
    wait_time.QuadPart = -100 * 1000 * 10; /* 100ms */
    KeDelayExecutionThread(KernelMode, FALSE, &wait_time);
  }
  
  KdPrint((__DRIVER_NAME "     Watch triggered on %s\n", path));
  RtlStringCbCopyA(tmp_path, ARRAY_SIZE(tmp_path), xsdd->vectors.backend_path);
  RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/vscsi-devs");
  msg = xsdd->vectors.XenBus_List(xsdd->vectors.context, XBT_NIL, tmp_path, &devices);
  if (msg)
  {
    /* this is pretty fatal ... */
    KdPrint((__DRIVER_NAME "     cannot read - %s\n", msg));
    return;
  }
  for (dev = (scsi_dev_t *)xsdd->dev_list_head.Flink;
    dev != (scsi_dev_t *)&xsdd->dev_list_head;
    dev = (scsi_dev_t *)dev->entry.Flink)
  {
    dev->validated = FALSE;
  }
  
  for (i = 0; devices[i]; i++)
  {
    if (strncmp(devices[i], "dev-", 4) != 0)
    {
      XenPci_FreeMem(devices[i]);
      break; /* not a dev so we are not interested */
    }
    dev_no = atoi(devices[i] + 4);
    RtlStringCbCopyA(tmp_path, ARRAY_SIZE(tmp_path), xsdd->vectors.backend_path);
    RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/vscsi-devs/");
    RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), devices[i]);
    RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/state");
    msg = xsdd->vectors.XenBus_Read(xsdd->vectors.context, XBT_NIL, tmp_path, &value);
    if (msg)
    {
      KdPrint((__DRIVER_NAME "     failed to read state for device %d\n", dev_no));
      state = 0;
    }
    else
      state = atoi(value);
    for (dev = (scsi_dev_t *)xsdd->dev_list_head.Flink;
      dev != (scsi_dev_t *)&xsdd->dev_list_head;
      dev = (scsi_dev_t * )dev->entry.Flink)
    {
      if (dev->dev_no == dev_no)
        break;
    }
    if (dev == (scsi_dev_t *)&xsdd->dev_list_head)
    {
      KdPrint((__DRIVER_NAME "     new dev %d\n", dev_no));
      dev = ExAllocatePoolWithTag(NonPagedPool, sizeof(scsi_dev_t), XENSCSI_POOL_TAG);
      dev->dev_no = dev_no;
      dev->state = state;
      dev->validated = TRUE;
      RtlStringCbCopyA(tmp_path, ARRAY_SIZE(tmp_path), xsdd->vectors.backend_path);
      RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/vscsi-devs/");
      RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), devices[i]);
      RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/v-dev");
      msg = xsdd->vectors.XenBus_Read(xsdd->vectors.context, XBT_NIL, tmp_path, &value);
      if (msg)
      {
        KdPrint((__DRIVER_NAME "     failed to read v-dev for device %d\n", dev_no));
        continue;
      }
      else
      {
        XenScsi_ParseBackendDevice(dev, value);
        // should verify that the controller = this
      }
      RtlStringCbCopyA(tmp_path, ARRAY_SIZE(tmp_path), xsdd->vectors.path);
      RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/vscsi-devs/");
      RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), devices[i]);
      RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/state");
      msg = xsdd->vectors.XenBus_Write(xsdd->vectors.context, XBT_NIL, tmp_path, "4");
      if (msg)
      {
        KdPrint((__DRIVER_NAME "     failed to write state %d to %s\n", 4, tmp_path));
        continue;
      }
      KdPrint((__DRIVER_NAME "     setting changes[%d]\n", dev->channel));
      xsdd->bus_changes[dev->channel] = 1;
      InsertTailList(&xsdd->dev_list_head, (PLIST_ENTRY)dev);
    }
    else
    {
      // need to manage state change
      // and write frontend state
      dev->state = state;
      dev->validated = TRUE;
      KdPrint((__DRIVER_NAME "     existing dev %d state = %d\n", dev_no, dev->state));
    }
    XenPci_FreeMem(devices[i]);
  }
  XenPci_FreeMem(devices);

  #if DBG
  oldpause =
  #endif
    InterlockedExchange(&xsdd->shared_paused, SHARED_PAUSED_PASSIVE_UNPAUSED);
  ASSERT(oldpause == SHARED_PAUSED_SCSIPORT_PAUSED);

  while (InterlockedCompareExchange(&xsdd->shared_paused, SHARED_PAUSED_SCSIPORT_UNPAUSED, SHARED_PAUSED_SCSIPORT_UNPAUSED) != SHARED_PAUSED_SCSIPORT_UNPAUSED)
  {
    KdPrint((__DRIVER_NAME "     Waiting for unpause...\n"));
    wait_time.QuadPart = -100 * 1000 * 10; /* 100ms */
    KeDelayExecutionThread(KernelMode, FALSE, &wait_time);
  }
  KdPrint((__DRIVER_NAME "     Unpaused\n"));

  FUNCTION_EXIT();
}
static VOID
XenBus_EvtIoWrite(WDFQUEUE queue, WDFREQUEST request, size_t length)
{
  NTSTATUS status;
  PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfIoQueueGetDevice(queue));
  WDFFILEOBJECT file_object = WdfRequestGetFileObject(request);
  PXENPCI_DEVICE_INTERFACE_DATA xpdid = GetXpdid(file_object);
  KIRQL old_irql;
  WDFREQUEST read_request;

  PUCHAR buffer;
  PUCHAR src_ptr;
  ULONG src_len;
  PUCHAR dst_ptr;
  ULONG copy_len;
  struct xsd_sockmsg *rep;
  xenbus_read_queue_item_t *list_entry;
  watch_context_t *watch_context;
  PCHAR watch_path;
  PCHAR watch_token;
  PCHAR msg;
  
  FUNCTION_ENTER();
  
  status = WdfRequestRetrieveInputBuffer(request, length, &buffer, NULL);
  ASSERT(NT_SUCCESS(status));
  
  src_ptr = (PUCHAR)buffer;
  src_len = (ULONG)length;
  dst_ptr = xpdid->xenbus.u.buffer + xpdid->xenbus.len;
  while (src_len != 0)
  {
    KdPrint((__DRIVER_NAME "     %d bytes of write buffer remaining\n", src_len));
    /* get a complete msg header */
    if (xpdid->xenbus.len < sizeof(xpdid->xenbus.u.msg))
    {
      copy_len = min(sizeof(xpdid->xenbus.u.msg) - xpdid->xenbus.len, src_len);
      if (!copy_len)
        continue;
      memcpy(dst_ptr, src_ptr, copy_len);
      dst_ptr += copy_len;
      src_ptr += copy_len;
      src_len -= copy_len;
      xpdid->xenbus.len += copy_len;
    }
    /* exit if we can't get that */
    if (xpdid->xenbus.len < sizeof(xpdid->xenbus.u.msg))
      continue;
    /* get a complete msg body */
    if (xpdid->xenbus.len < sizeof(xpdid->xenbus.u.msg) + xpdid->xenbus.u.msg.len)
    {
      copy_len = min(sizeof(xpdid->xenbus.u.msg) + xpdid->xenbus.u.msg.len - xpdid->xenbus.len, src_len);
      if (!copy_len)
        continue;
      memcpy(dst_ptr, src_ptr, copy_len);
      dst_ptr += copy_len;
      src_ptr += copy_len;
      src_len -= copy_len;
      xpdid->xenbus.len += copy_len;
    }
    /* exit if we can't get that */
    if (xpdid->xenbus.len < sizeof(xpdid->xenbus.u.msg) + xpdid->xenbus.u.msg.len)
    {
      continue;
    }
    
    switch (xpdid->xenbus.u.msg.type)
    {
    case XS_WATCH:
    case XS_UNWATCH:
      KeAcquireSpinLock(&xpdid->lock, &old_irql);
      watch_context = (watch_context_t *)ExAllocatePoolWithTag(NonPagedPool, sizeof(watch_context_t), XENPCI_POOL_TAG);
      watch_path = (PCHAR)(xpdid->xenbus.u.buffer + sizeof(struct xsd_sockmsg));
      watch_token = (PCHAR)(xpdid->xenbus.u.buffer + sizeof(struct xsd_sockmsg) + strlen(watch_path) + 1);
      RtlStringCbCopyA(watch_context->path, ARRAY_SIZE(watch_context->path), watch_path);
      RtlStringCbCopyA(watch_context->token, ARRAY_SIZE(watch_context->path), watch_token);
      watch_context->file_object = file_object;
      if (xpdid->xenbus.u.msg.type == XS_WATCH)
        InsertTailList(&xpdid->xenbus.watch_list_head, &watch_context->entry);
      KeReleaseSpinLock(&xpdid->lock, old_irql);
      if (xpdid->xenbus.u.msg.type == XS_WATCH)
        msg = XenBus_AddWatch(xpdd, XBT_NIL, watch_path, XenPci_IoWatch, watch_context);
      else
        msg = XenBus_RemWatch(xpdd, XBT_NIL, watch_path, XenPci_IoWatch, watch_context);
      KeAcquireSpinLock(&xpdid->lock, &old_irql);
      if (msg != NULL)
      {
        rep = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct xsd_sockmsg) + strlen(msg) + 1, XENPCI_POOL_TAG);
        rep->type = XS_ERROR;
        rep->req_id = xpdid->xenbus.u.msg.req_id;
        rep->tx_id = xpdid->xenbus.u.msg.tx_id;
        rep->len = (ULONG)(strlen(msg) + 0);
        RtlStringCbCopyA((PCHAR)(rep + 1), strlen(msg) + 1, msg);
        if (xpdid->xenbus.u.msg.type == XS_WATCH)
          RemoveEntryList(&watch_context->entry);
      }
      else
      {
        if (xpdid->xenbus.u.msg.type == XS_WATCH)
        {
          WdfObjectReference(file_object);
        }
        else
        {
          RemoveEntryList(&watch_context->entry);
          WdfObjectDereference(file_object);
        }
        rep = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct xsd_sockmsg), XENPCI_POOL_TAG);
        rep->type = xpdid->xenbus.u.msg.type;
        rep->req_id = xpdid->xenbus.u.msg.req_id;
        rep->tx_id = xpdid->xenbus.u.msg.tx_id;
        rep->len = 0;
      }
      KeReleaseSpinLock(&xpdid->lock, old_irql);
      break;
    default:
      rep = XenBus_Raw(xpdd, &xpdid->xenbus.u.msg);
      break;
    }
    xpdid->xenbus.len = 0;
    
    KeAcquireSpinLock(&xpdid->lock, &old_irql);
    list_entry = (xenbus_read_queue_item_t *)ExAllocatePoolWithTag(NonPagedPool, sizeof(xenbus_read_queue_item_t), XENPCI_POOL_TAG);
    list_entry->data = rep;
    list_entry->length = sizeof(*rep) + rep->len;
    list_entry->offset = 0;
    InsertTailList(&xpdid->xenbus.read_list_head, (PLIST_ENTRY)list_entry);

	// Check if someone was waiting for the answer already
	status = WdfIoQueueRetrieveNextRequest(xpdid->xenbus.io_queue, &read_request);
    if (NT_SUCCESS(status))
    {
		WDF_REQUEST_PARAMETERS parameters;
		KdPrint((__DRIVER_NAME "     post-write: found pending read\n"));
		WDF_REQUEST_PARAMETERS_INIT(&parameters);
		WdfRequestGetParameters(read_request, &parameters);
		XenBus_ProcessReadRequest(xpdid->xenbus.io_queue, read_request, parameters.Parameters.Read.Length);
		WdfRequestComplete(read_request, STATUS_SUCCESS);
    }
    else
    {
		KdPrint((__DRIVER_NAME "     post-write: no pending read (%08x)\n", status));
    }

    KeReleaseSpinLock(&xpdid->lock, old_irql);
  }
  KdPrint((__DRIVER_NAME "     completing request with length %d\n", length));
  WdfRequestCompleteWithInformation(request, STATUS_SUCCESS, length);

  FUNCTION_EXIT();
}
Ejemplo n.º 10
0
NTSTATUS
XenPci_EvtChildListCreateDevice(WDFCHILDLIST child_list,
  PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER identification_header,
  PWDFDEVICE_INIT child_init) {
  NTSTATUS status = STATUS_SUCCESS;
  WDF_OBJECT_ATTRIBUTES child_attributes;
  WDFDEVICE child_device;
  PXENPCI_PDO_IDENTIFICATION_DESCRIPTION identification = (PXENPCI_PDO_IDENTIFICATION_DESCRIPTION)identification_header;
  WDF_DEVICE_PNP_CAPABILITIES child_pnp_capabilities;
  DECLARE_UNICODE_STRING_SIZE(buffer, 512);
  DECLARE_CONST_UNICODE_STRING(location, L"Xen Bus");
  PXENPCI_PDO_DEVICE_DATA xppdd;
  PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfChildListGetDevice(child_list));
  //WDF_PDO_EVENT_CALLBACKS pdo_callbacks;
  WDF_PNPPOWER_EVENT_CALLBACKS child_pnp_power_callbacks;
  //UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE };
  WDF_DEVICE_POWER_CAPABILITIES child_power_capabilities;
  
  FUNCTION_ENTER();

  WdfDeviceInitSetDeviceType(child_init, FILE_DEVICE_UNKNOWN);
  
  WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&child_pnp_power_callbacks);
  child_pnp_power_callbacks.EvtDeviceD0Entry = XenPciPdo_EvtDeviceD0Entry;
  child_pnp_power_callbacks.EvtDeviceD0Exit = XenPciPdo_EvtDeviceD0Exit;
  child_pnp_power_callbacks.EvtDeviceUsageNotification = XenPciPdo_EvtDeviceUsageNotification;
  WdfDeviceInitSetPnpPowerEventCallbacks(child_init, &child_pnp_power_callbacks);

  FUNCTION_MSG("device = '%s', index = '%d', path = '%s'\n",
    identification->device, identification->index, identification->path);
  
  //status = WdfDeviceInitAssignWdmIrpPreprocessCallback(child_init, XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE,
  //  IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
  //if (!NT_SUCCESS(status)) {
  //  return status;
  //}
  
  //WDF_PDO_EVENT_CALLBACKS_INIT(&pdo_callbacks);
  //pdo_callbacks.EvtDeviceResourcesQuery = XenPciPdo_EvtDeviceResourcesQuery;
  //pdo_callbacks.EvtDeviceResourceRequirementsQuery = XenPciPdo_EvtDeviceResourceRequirementsQuery;
  //pdo_callbacks.EvtDeviceEject = XenPciPdo_EvtDeviceEject;
  //pdo_callbacks.EvtDeviceSetLock  = XenPciPdo_EvtDeviceSetLock;
  //WdfPdoInitSetEventCallbacks(child_init, &pdo_callbacks);

  RtlUnicodeStringPrintf(&buffer, L"xen\\%S", identification->device);
  status = WdfPdoInitAssignDeviceID(child_init, &buffer);
  if (!NT_SUCCESS(status))
  {
    return status;
  }
  status = WdfPdoInitAddHardwareID(child_init, &buffer);
  if (!NT_SUCCESS(status))
  {
    return status;
  }
  status = WdfPdoInitAddCompatibleID(child_init, &buffer);
  if (!NT_SUCCESS(status))
  {
    return status;
  }
  
  RtlUnicodeStringPrintf(&buffer, L"%02d", identification->index);
  status = WdfPdoInitAssignInstanceID(child_init, &buffer);
  if (!NT_SUCCESS(status))
  {
    return status;
  }
  
  RtlUnicodeStringPrintf(&buffer, L"Xen %S device #%d", identification->device, identification->index);
  status = WdfPdoInitAddDeviceText(child_init, &buffer, &location, 0x0409);
  if (!NT_SUCCESS(status))
  {
    return status;
  }
  WdfPdoInitSetDefaultLocale(child_init, 0x0409);

  WdfDeviceInitSetPowerNotPageable(child_init);

  WdfDeviceInitRegisterPnpStateChangeCallback(child_init, WdfDevStatePnpQueryCanceled, XenPci_EvtDevicePnpStateChange, StateNotificationEnterState);
  
  WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&child_attributes, XENPCI_PDO_DEVICE_DATA);
  status = WdfDeviceCreate(&child_init, &child_attributes, &child_device);
  if (!NT_SUCCESS(status))
  {
    return status;
  }

  xppdd = GetXppdd(child_device);
  
  xppdd->wdf_device = child_device;
  xppdd->wdf_device_bus_fdo = WdfChildListGetDevice(child_list);
  xppdd->xpdd = xpdd;

  WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFilePaging, TRUE);
  WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileHibernation, TRUE);
  WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileDump, TRUE);

  WDF_DEVICE_PNP_CAPABILITIES_INIT(&child_pnp_capabilities);
  child_pnp_capabilities.LockSupported = WdfFalse;
  child_pnp_capabilities.EjectSupported  = WdfTrue;
  child_pnp_capabilities.Removable  = WdfTrue;
  child_pnp_capabilities.DockDevice  = WdfFalse;
  child_pnp_capabilities.UniqueID  = WdfFalse;
  child_pnp_capabilities.SilentInstall  = WdfTrue;
  child_pnp_capabilities.SurpriseRemovalOK  = WdfTrue;
  child_pnp_capabilities.HardwareDisabled = WdfFalse;
  WdfDeviceSetPnpCapabilities(child_device, &child_pnp_capabilities);

  WDF_DEVICE_POWER_CAPABILITIES_INIT(&child_power_capabilities);
  child_power_capabilities.DeviceD1 = WdfTrue;
  child_power_capabilities.WakeFromD1 = WdfTrue;
  child_power_capabilities.DeviceWake = PowerDeviceD1;
  child_power_capabilities.DeviceState[PowerSystemWorking]   = PowerDeviceD0;
  child_power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
  child_power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
  child_power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
  child_power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
  child_power_capabilities.DeviceState[PowerSystemShutdown]  = PowerDeviceD3;
  WdfDeviceSetPowerCapabilities(child_device, &child_power_capabilities);  

  RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), identification->path);
  RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), identification->device);
  xppdd->index = identification->index;
  KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
  ExInitializeFastMutex(&xppdd->backend_state_mutex);
  xppdd->backend_state = XenbusStateUnknown;
  xppdd->frontend_state = XenbusStateUnknown;
  xppdd->backend_path[0] = '\0';
  xppdd->backend_id = 0;
    
  FUNCTION_EXIT();
  
  return status;
}
VOID
FxDriver::_InitializeDriverName(
    __in PFX_DRIVER_GLOBALS FxDriverGlobals,
    __in PCUNICODE_STRING RegistryPath
    )
/*++

Routine Description:
    Create a CHAR version of the service name contained in RegistryPath.

Arguments:
    RegistryPath - the path to the service name in the registry.

Return Value:
    None

  --*/
{
    PWCHAR pCur, pBegin, pEnd;

    RtlZeroMemory(&FxDriverGlobals->Public.DriverName[0],
                  sizeof(FxDriverGlobals->Public.DriverName) );

    if (RegistryPath == NULL) {
        return;
    }

    pBegin = RegistryPath->Buffer;

    //
    // pEnd is one past the end of the string, while pCur is a pointer to the
    // last character of the string.  We will decrement pCur down towards the
    // beginning of the string.
    //
    pEnd = pBegin + (RegistryPath->Length / sizeof(WCHAR));
    pCur = pEnd - 1;

    for ( ; *pCur != L'\\' && pCur != pBegin; pCur--) {
        DO_NOTHING();
    }

    if (pCur != pBegin && *pCur == L'\\') {
        size_t regLen;
        ULONG i;

        pCur++;

        //
        // Can't use wcslen becuase this is a UNICODE_STRING which means that it
        // does not necessarily have a terminating NULL in the buffer.
        //
        regLen = pEnd - pCur;
        if (regLen > WDF_DRIVER_GLOBALS_NAME_LEN-1) {
            regLen = WDF_DRIVER_GLOBALS_NAME_LEN-1;
        }


        for (i = 0; i < regLen; i++) {
            FxDriverGlobals->Public.DriverName[i] = (CHAR) pCur[i];
        }
    }
    else {
        NTSTATUS status;
        
#if FX_CORE_MODE==FX_CORE_KERNEL_MODE        
        status = RtlStringCbCopyA(FxDriverGlobals->Public.DriverName,
                                  sizeof(FxDriverGlobals->Public.DriverName),
                                  "WDF");
#else // USER_MODE
        HRESULT hr;
        hr = StringCbCopyA(FxDriverGlobals->Public.DriverName,
                           sizeof(FxDriverGlobals->Public.DriverName),
                           "WDF");
        if (HRESULT_FACILITY(hr) == FACILITY_WIN32) {        
            status = WinErrorToNtStatus(HRESULT_CODE(hr));
        } 
        else {
            status = SUCCEEDED(hr) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
        }
#endif
       
        UNREFERENCED_PARAMETER(status);
        ASSERT(NT_SUCCESS(status));
    }
}
Ejemplo n.º 12
0
PINTERNAL_SYMBOL SymGetSymbols(OUT PULONG puSymbolCount)
{
	ASSERTMSG("SymbolEngine must be initialized prior to this call", bIsSymEngineInitialized == TRUE);
	ASSERTMSG("Pointer to number of currently defined symbols must not be NULL", puSymbolCount != NULL);

	PLIST_ENTRY symbolListEntry = SymbolsListHead.Flink;

	*puSymbolCount = SymGetSymbolCount();

	// check if there are symbols in the list
	if(*puSymbolCount == 0)
	{
		KdPrint(("[DEBUG] No symbols in the list!\n"));
		return NULL;
	}

	// allocate memory for the INTERNAL_SYMBOL array
	PINTERNAL_SYMBOL pInternalSymbolArray = (PINTERNAL_SYMBOL) ExAllocatePoolWithTag(	NonPagedPool,								// must be NonPaged
																						*puSymbolCount * sizeof(INTERNAL_SYMBOL),
																						TAG_INTERNAL_SYMBOL_ARRAY					// Syma(rray)
																					  );

	if(pInternalSymbolArray == NULL)
	{
		KdPrint(("[DEBUG] ERROR - Unable to allocate memory for internal symbol array!\n"));
		return NULL;
	}

	// iterate through symbols list
	ULONG uSymIndex = 0;
	ASSERTMSG("Fast mutex acquire must occur at or below APC_LEVEL", KeGetCurrentIrql() <= APC_LEVEL);
	ExAcquireFastMutex(&SymbolsListMutex);
	while(symbolListEntry != &SymbolsListHead)
	{
		PSYMBOL_ENTRY pSymbolEntry = CONTAINING_RECORD(symbolListEntry, SYMBOL_ENTRY, ListEntry);
		
		// copy name of the symbol
		if(RtlStringCbCopyA(pInternalSymbolArray[uSymIndex].name, MAX_SYM_NAME, pSymbolEntry->Symbol.name) == STATUS_INVALID_PARAMETER)
		{
			KdPrint(("[DEBUG] ERROR - Error while copying symbol name to INTERNAL_SYMBOL structure\n"));
			return NULL;
		}

		// copy address from the symbol in the list
		pInternalSymbolArray[uSymIndex].u64address = pSymbolEntry->Symbol.u64address;

		// copy offset from the symbol in the list
		pInternalSymbolArray[uSymIndex].uOffset = pSymbolEntry->Symbol.uOffset;

		// copy bit position from the symbol in the list
		pInternalSymbolArray[uSymIndex].uBitPosition = pSymbolEntry->Symbol.uBitPosition;

		// copy bit length from the symbol in the list
		pInternalSymbolArray[uSymIndex].uBitLength = pSymbolEntry->Symbol.uBitLength;
		
		uSymIndex++;
		symbolListEntry = symbolListEntry->Flink;
	}

	// release mutex before returning the list to the main program
	ASSERTMSG("Fast mutex release must occur at APC_LEVEL", KeGetCurrentIrql() == APC_LEVEL);
	ExReleaseFastMutex(&SymbolsListMutex);
	return pInternalSymbolArray;
}