예제 #1
0
void
AhciDumpCurrentState(
    _In_ AhciController_t* Controller, 
    _In_ AhciPort_t*       Port)
{
    // When trace is disabled
    _CRT_UNUSED(Controller);
    _CRT_UNUSED(Port);

    // Dump registers
    WARNING("AHCI.GlobalHostControl 0x%x",
        Controller->Registers->GlobalHostControl);
    WARNING("AHCI.InterruptStatus 0x%x",
        Controller->Registers->InterruptStatus);
    WARNING("AHCI.CcControl 0x%x",
        Controller->Registers->CcControl);

    WARNING("AHCI.Port[%i].CommandAndStatus 0x%x", Port->Id,
        Port->Registers->CommandAndStatus);
    WARNING("AHCI.Port[%i].InterruptEnable 0x%x", Port->Id,
        Port->Registers->InterruptEnable);
    WARNING("AHCI.Port[%i].InterruptStatus 0x%x", Port->Id,
        Port->Registers->InterruptStatus);
    WARNING("AHCI.Port[%i].CommandIssue 0x%x", Port->Id,
        Port->Registers->CommandIssue);
    WARNING("AHCI.Port[%i].TaskFileData 0x%x", Port->Id,
        Port->Registers->TaskFileData);

    WARNING("AHCI.Port[%i].AtaError 0x%x", Port->Id,
        Port->Registers->AtaError);
    WARNING("AHCI.Port[%i].AtaStatus 0x%x", Port->Id,
        Port->Registers->AtaStatus);
}
예제 #2
0
InterruptStatus_t 
OnInterrupt(
    _In_Opt_ void*  InterruptData,
    _In_Opt_ size_t Arg0,
    _In_Opt_ size_t Arg1,
    _In_Opt_ size_t Arg2)
{
    UhciController_t* Controller = NULL;
    uint16_t          InterruptStatus;
    
    // Unusued
    _CRT_UNUSED(Arg0);
    _CRT_UNUSED(Arg1);
    _CRT_UNUSED(Arg2);

    Controller = (UhciController_t*)InterruptData;

HandleInterrupt:
    InterruptStatus                  = Controller->Base.InterruptStatus;
    Controller->Base.InterruptStatus = 0;
    // If either interrupt or error is present, it means a change happened
    // in one of our transactions
    if (InterruptStatus & (UHCI_STATUS_USBINT | UHCI_STATUS_INTR_ERROR)) {
        UhciUpdateCurrentFrame(Controller);
        UsbManagerProcessTransfers(&Controller->Base);
    }

    // The controller is telling us to perform resume
    if (InterruptStatus & UHCI_STATUS_RESUME_DETECT) {
        UhciStart(Controller, 0);
    }

    // If an host error occurs we should restart controller
    if (InterruptStatus & UHCI_STATUS_HOST_SYSERR) {
        UhciReset(Controller);
        UhciStart(Controller, 0);
    }

    // Processing error, queue stopped
    if (InterruptStatus & UHCI_STATUS_PROCESS_ERR) {
        // Clear queue and all waiting
        UhciQueueReset(Controller);
        UhciReset(Controller);
        UhciStart(Controller, 0);
    }

    // Make sure we re-handle interrupts meanwhile
    if (Controller->Base.InterruptStatus != 0) {
        goto HandleInterrupt;
    }
    return InterruptHandled;
}
예제 #3
0
파일: pit.c 프로젝트: Fadekraft/MollenOS
/* PitInterrupt
 * Calls the timer interface to tick the system tick. */
InterruptStatus_t
PitInterrupt(
    _In_ FastInterruptResources_t*  NotUsed,
    _In_ void*                      Context)
{
    // Unused
    _CRT_UNUSED(NotUsed);
	_CRT_UNUSED(Context);

	// Update stats
	PitUnit.NsCounter += PitUnit.NsTick;
	PitUnit.Ticks++;
    TimersInterrupt(PitUnit.Irq);
	return InterruptHandled;
}
예제 #4
0
_CRTIMP2_PURE short __CLRCALL_PURE_OR_CDECL _Getwctype(wchar_t _Ch,
	const _Ctypevec *_Ctype)
	{	/* return character classification flags for _Ch */
	_CRT_UNUSED(_Ctype);
	short _Mask;
	return ((short)(GetStringTypeW(CT_CTYPE1, &_Ch, 1,
		(LPWORD)&_Mask) == 0
		? 0 : _Mask));
	}
예제 #5
0
_CRTIMP2_PURE const wchar_t * __CLRCALL_PURE_OR_CDECL _Getwctypes(
	const wchar_t *_First, const wchar_t *_Last,
		short *_Dest, const _Ctypevec *_Ctype)
	{	/* get mask sequence for elements in [_First, _Last) */
	_CRT_UNUSED(_Ctype);
	GetStringTypeW(CT_CTYPE1, _First, (int)(_Last - _First),
		(LPWORD)_Dest);
	return (_Last);
	}
예제 #6
0
int iswcntrl_l(wint_t c, struct __locale_t *locale)
{
	/* Silence warning */
	_CRT_UNUSED(locale);

	/* We're using a locale-independent representation of upper/lower case
	   based on Unicode data.  Thus, the locale doesn't matter. */
	return iswcntrl (c);
}
예제 #7
0
파일: Pit.c 프로젝트: Fluray/MollenOS
/* Entry point of a module */
MODULES_API void ModuleInit(void *Data)
{
	/* We need these */
	MCoreDevice_t *Device = NULL;
	MCoreTimerDevice_t *Timer = NULL;
	PitTimer_t *Pit = NULL;

	/* We want a frequncy of 1000 hz */
	uint32_t Divisor = (1193181 / 1000);
	IntStatus_t IntrState;

	/* Unused */
	_CRT_UNUSED(Data);

	/* Allocate */
	Device = (MCoreDevice_t*)kmalloc(sizeof(MCoreDevice_t));
	Pit = (PitTimer_t*)kmalloc(sizeof(PitTimer_t));
	Timer = (MCoreTimerDevice_t*)kmalloc(sizeof(MCoreTimerDevice_t));

	/* Disable IRQ's for this duration */
	IntrState = InterruptDisable();
	Pit->PitCounter = 0;
	Pit->Divisor = Divisor;

	/* Setup Timer */
	Timer->TimerData = Pit;
	Timer->Sleep = PitSleep;
	Timer->Stall = PitStall;
	Timer->GetTicks = PitGetClocks;

	/* Install Irq */
	InterruptInstallISA(X86_PIT_IRQ, INTERRUPT_PIT, PitIrqHandler, Timer);

	/* Before enabling, register us */
	Pit->DeviceId = DmCreateDevice("PIT Timer", DeviceTimer, Timer);

	/* We use counter 0, select counter 0 and configure it */
	outb(X86_PIT_REGISTER_COMMAND,
		X86_PIT_COMMAND_SQUAREWAVEGEN |
		X86_PIT_COMMAND_RL_DATA |
		X86_PIT_COMMAND_COUNTER_0);

	/* Set divisor */
	outb(X86_PIT_REGISTER_COUNTER0, (uint8_t)(Divisor & 0xFF));
	outb(X86_PIT_REGISTER_COUNTER0, (uint8_t)((Divisor >> 8) & 0xFF));

	/* Done, reenable interrupts */
	InterruptRestoreState(IntrState);
}
예제 #8
0
int __numeric_load_locale (struct __locale_t *locale, const char *name ,
		       void *f_wctomb, const char *charset)
{
  int ret = 0;
  struct lc_numeric_T nm;
  char *bufp = NULL;

#ifdef __CYGWIN__
  extern int __set_lc_numeric_from_win (const char *,
					const struct lc_numeric_T *,
					struct lc_numeric_T *, char **,
					void *, const char *);
  ret = __set_lc_numeric_from_win (name, &_C_numeric_locale, &nm, &bufp,
				   f_wctomb, charset);
  /* ret == -1: error, ret == 0: C/POSIX, ret > 0: valid */
  if (ret >= 0)
    {
      struct lc_numeric_T *nmp = NULL;

      if (ret > 0)
	{
	  nmp = (struct lc_numeric_T *) calloc (1, sizeof *nmp);
	  if (!nmp)
	    {
	      free (bufp);
	      return -1;
	    }
	  *nmp = nm;
	}
      struct __lc_cats tmp = locale->lc_cat[LC_NUMERIC];
      locale->lc_cat[LC_NUMERIC].ptr = ret == 0 ? &_C_numeric_locale : nmp;
      locale->lc_cat[LC_NUMERIC].buf = bufp;
      /* If buf is not NULL, both pointers have been alloc'ed */
      if (tmp.buf)
	{
	  free ((void *) tmp.ptr);
	  free (tmp.buf);
	}
      ret = 0;
    }
#else
	/* TODO */
	_CRT_UNUSED(bufp);
	_CRT_UNUSED(nm);
	_CRT_UNUSED(locale);
	_CRT_UNUSED(name);
	_CRT_UNUSED(f_wctomb);
	_CRT_UNUSED(charset);
#endif
  return ret;
}
예제 #9
0
int __monetary_load_locale (struct __locale_t *locale, const char *name ,
			void *f_wctomb, const char *charset)
{
  int ret = 0;
  struct lc_monetary_T mo;
  char *bufp = NULL;

#ifdef __CYGWIN__
  extern int __set_lc_monetary_from_win (const char *,
					 const struct lc_monetary_T *,
					 struct lc_monetary_T *, char **,
					 void *, const char *);
  ret = __set_lc_monetary_from_win (name, &_C_monetary_locale, &mo, &bufp,
				    f_wctomb, charset);
  /* ret == -1: error, ret == 0: C/POSIX, ret > 0: valid */
  if (ret >= 0)
    {
      struct lc_monetary_T *mop = NULL;

      if (ret > 0)
	{
	  mop = (struct lc_monetary_T *) calloc (1, sizeof *mop);
	  if (!mop)
	    {
	      free (bufp);
	      return -1;
	    }
	  *mop = mo;
	}
      struct __lc_cats tmp = locale->lc_cat[LC_MONETARY];
      locale->lc_cat[LC_MONETARY].ptr = ret == 0 ? &_C_monetary_locale : mop;
      locale->lc_cat[LC_MONETARY].buf = bufp;
      /* If buf is not NULL, both pointers have been alloc'ed */
      if (tmp.buf)
	{
	  free ((void *) tmp.ptr);
	  free (tmp.buf);
	}
      ret = 0;
    }
#else
  /* TODO */
  _CRT_UNUSED(bufp);
  _CRT_UNUSED(mo);
  _CRT_UNUSED(locale);
  _CRT_UNUSED(name);
  _CRT_UNUSED(f_wctomb);
  _CRT_UNUSED(charset);
#endif
  return ret;
}
예제 #10
0
InterruptStatus_t
OnFastInterrupt(
    _In_ FastInterruptResources_t* InterruptTable,
    _In_ void*                     NotUsed)
{
    UhciController_t* Controller = (UhciController_t*)INTERRUPT_RESOURCE(InterruptTable, 0);
    DeviceIo_t*       IoSpace    = INTERRUPT_IOSPACE(InterruptTable, 0);
    uint16_t          InterruptStatus;
    _CRT_UNUSED(NotUsed);

    // Was the interrupt even from this controller?
    InterruptStatus = LOWORD(InterruptTable->ReadIoSpace(IoSpace, UHCI_REGISTER_STATUS, 2));
    if (!(InterruptStatus & UHCI_STATUS_INTMASK)) {
        return InterruptNotHandled;
    }
    Controller->Base.InterruptStatus |= InterruptStatus;

    // Clear interrupt bits
    InterruptTable->WriteIoSpace(IoSpace, UHCI_REGISTER_STATUS, InterruptStatus, 2);
    return InterruptHandled;
}
예제 #11
0
void freelocale(struct __locale_t *locobj)
{
  /* Nothing to do on !_MB_CAPABLE targets. */
#ifdef _MB_CAPABLE
  /* Sanity check.  The "C" locale is static, don't try to free it. */
  if (!locobj || locobj == __get_C_locale () || locobj == LC_GLOBAL_LOCALE)
    return;
#ifdef __HAVE_LOCALE_INFO__
  for (int i = 1; i < _LC_LAST; ++i)
    if (locobj->lc_cat[i].buf)
      {
	_free_r (p, (void *) locobj->lc_cat[i].ptr);
	_free_r (p, locobj->lc_cat[i].buf);
      }
#endif /* __HAVE_LOCALE_INFO__ */
  _free_r (p, locobj);
#else
	/* Silence warning */
	_CRT_UNUSED(locobj);
#endif /* _MB_CAPABLE */
}
예제 #12
0
파일: Vfs.c 프로젝트: Fluray/MollenOS
/* Partition table parser */
int VfsParsePartitionTable(DevId_t DiskId, uint64_t SectorBase, uint64_t SectorCount, uint32_t SectorSize)
{
	/* Allocate structures */
	void *TmpBuffer = (void*)kmalloc(SectorSize);
	MCoreModule_t *Module = NULL;
	MCoreMasterBootRecord_t *Mbr = NULL;
	MCoreDeviceRequest_t Request;
	int PartitionCount = 0;
	int i;

	/* Read sector */
	Request.Type = RequestRead;
	Request.DeviceId = DiskId;
	Request.SectorLBA = SectorBase;
	Request.Buffer = (uint8_t*)TmpBuffer;
	Request.Length = SectorSize;

	/* Create & Wait */
	DmCreateRequest(&Request);
	DmWaitRequest(&Request);

	/* Sanity */
	if (Request.Status != RequestOk)
	{
		/* Error */
		LogFatal("VFSM", "REGISTERDISK: Error reading from disk - 0x%x\n", Request.Status);
		kfree(TmpBuffer);
		return 0;
	}

	_CRT_UNUSED(SectorCount);
	/* Cast */
	Mbr = (MCoreMasterBootRecord_t*)TmpBuffer;

	/* Valid partition table? */
	for (i = 0; i < 4; i++)
	{
		/* Is it an active partition? */
		if (Mbr->Partitions[i].Status == PARTITION_ACTIVE)
		{
			/* Inc */
			PartitionCount++;

			/* Allocate a filesystem structure */
			MCoreFileSystem_t *Fs = (MCoreFileSystem_t*)kmalloc(sizeof(MCoreFileSystem_t));
			Fs->State = VfsStateInit;
			Fs->DiskId = DiskId;
			Fs->FsData = NULL;
			Fs->SectorStart = SectorBase + Mbr->Partitions[i].LbaSector;
			Fs->SectorCount = Mbr->Partitions[i].LbaSize;
			Fs->Id = GlbFileSystemId;
			Fs->SectorSize = SectorSize;

			/* Check extended partitions first */
			if (Mbr->Partitions[i].Type == 0x05)
			{
				/* Extended - CHS */
			}
			else if (Mbr->Partitions[i].Type == 0x0F
				|| Mbr->Partitions[i].Type == 0xCF)
			{
				/* Extended - LBA */
				PartitionCount += VfsParsePartitionTable(DiskId,
					SectorBase + Mbr->Partitions[i].LbaSector, Mbr->Partitions[i].LbaSize, SectorSize);
			}
			else if (Mbr->Partitions[i].Type == 0xEE)
			{
				/* GPT Formatted */
			}

			/* Check MFS */
			else if (Mbr->Partitions[i].Type == 0x61)
			{
				/* MFS 1 */
				Module = ModuleFind(MODULE_FILESYSTEM, FILESYSTEM_MFS);

				/* Load */
				if (Module != NULL)
					ModuleLoad(Module, Fs);
			}

			/* Check FAT */
			else if (Mbr->Partitions[i].Type == 0x1
				|| Mbr->Partitions[i].Type == 0x6
				|| Mbr->Partitions[i].Type == 0x8 /* Might be FAT16 */
				|| Mbr->Partitions[i].Type == 0x11 /* Might be FAT16 */
				|| Mbr->Partitions[i].Type == 0x14 /* Might be FAT16 */
				|| Mbr->Partitions[i].Type == 0x24 /* Might be FAT16 */
				|| Mbr->Partitions[i].Type == 0x56 /* Might be FAT16 */
				|| Mbr->Partitions[i].Type == 0x8D
				|| Mbr->Partitions[i].Type == 0xAA
				|| Mbr->Partitions[i].Type == 0xC1
				|| Mbr->Partitions[i].Type == 0xD1
				|| Mbr->Partitions[i].Type == 0xE1
				|| Mbr->Partitions[i].Type == 0xE5
				|| Mbr->Partitions[i].Type == 0xEF
				|| Mbr->Partitions[i].Type == 0xF2)
			{
				/* Fat-12 */
			}
			else if (Mbr->Partitions[i].Type == 0x4
				|| Mbr->Partitions[i].Type == 0x6
				|| Mbr->Partitions[i].Type == 0xE
				|| Mbr->Partitions[i].Type == 0x16
				|| Mbr->Partitions[i].Type == 0x1E
				|| Mbr->Partitions[i].Type == 0x90
				|| Mbr->Partitions[i].Type == 0x92
				|| Mbr->Partitions[i].Type == 0x9A
				|| Mbr->Partitions[i].Type == 0xC4
				|| Mbr->Partitions[i].Type == 0xC6
				|| Mbr->Partitions[i].Type == 0xCE
				|| Mbr->Partitions[i].Type == 0xD4
				|| Mbr->Partitions[i].Type == 0xD6)
			{
				/* Fat16 */
			}
			else if (Mbr->Partitions[i].Type == 0x0B /* CHS */
				|| Mbr->Partitions[i].Type == 0x0C /* LBA */
				|| Mbr->Partitions[i].Type == 0x27
				|| Mbr->Partitions[i].Type == 0xCB
				|| Mbr->Partitions[i].Type == 0xCC)
			{
				/* Fat32 */
			}

			/* Lastly */
			if (Fs->State == VfsStateActive)
				VfsInstallFileSystem(Fs);
			else
				kfree(Fs);
		}
	}

	/* Done */
	kfree(TmpBuffer);
	return PartitionCount;
}
예제 #13
0
/* Request Thread */
void DmRequestHandler(void *Args)
{
	/* Vars */
	list_node_t *lNode;
	MCoreDeviceRequest_t *Request;

	/* Unused */
	_CRT_UNUSED(Args);

	while (1)
	{
		/* Acquire Semaphore */
		SemaphoreP(GlbDmEventLock);

		/* Pop Request */
		lNode = list_pop_front(GlbDmEventQueue);

		/* Sanity */
		if (lNode == NULL)
			continue;

		/* Cast */
		Request = (MCoreDeviceRequest_t*)lNode->data;

		/* Free the node */
		kfree(lNode);

		/* Again, sanity */
		if (Request == NULL)
			continue;

		/* Lookup Device */
		MCoreDevice_t *Dev =
			(MCoreDevice_t*)list_get_data_by_id(GlbDmDeviceList, Request->DeviceId, 0);

		/* Sanity */
		if (Dev == NULL)
		{
			/* Set status */
			Request->Status = RequestDeviceIsRemoved;

			/* We are done, wakeup */
			SchedulerWakeupAllThreads((Addr_t*)Request);

			/* Next! */
			continue;
		}

		/* Set initial status */
		Request->Status = RequestInProgress;

		/* Handle Event */
		switch (Request->Type)
		{
			/* Read from Device */
			case RequestQuery:
			{
				/* Sanity type */
				if (Dev->Type == DeviceStorage)
				{
					/* Cast again */
					MCoreStorageDevice_t *Disk = (MCoreStorageDevice_t*)Dev->Data;

					/* Validate buffer */
					if (Request->Buffer == NULL
						|| Request->Length < 20)
						Request->Status = RequestInvalidParameters;
					else
					{
						/* Copy the first 20 bytes that contains stats */
						memcpy(Request->Buffer, Disk, 20);

						/* Done */
						Request->Status = RequestOk;
					}
				}
				else if (Dev->Type == DeviceVideo)
				{
					/* Cast again */
					MCoreVideoDevice_t *Video = (MCoreVideoDevice_t*)Dev->Data;

					/* Validate buffer */
					if (Request->Buffer == NULL
						|| Request->Length < sizeof(MCoreVideoDescriptor_t))
						Request->Status = RequestInvalidParameters;
					else
					{
						/* Copy the descriptor */
						memcpy(Request->Buffer, &Video->Info, sizeof(MCoreVideoDescriptor_t));

						/* Done */
						Request->Status = RequestOk;
					}
				}

			} break;

			/* Read from Device */
			case RequestRead:
			{
				/* Sanity type */
				if (Dev->Type == DeviceStorage)
				{
					/* Cast again */
					MCoreStorageDevice_t *Disk = (MCoreStorageDevice_t*)Dev->Data;

					/* Validate parameters */

					/* Perform */
					if (Disk->Read(Disk->DiskData, Request->SectorLBA, Request->Buffer, Request->Length) != 0)
						Request->Status = RequestDeviceError;
					else
						Request->Status = RequestOk;
				}

			} break;

			/* Write to Device */
			case RequestWrite:
			{
				/* Sanity type */
				if (Dev->Type == DeviceStorage)
				{
					/* Cast again */
					MCoreStorageDevice_t *Disk = (MCoreStorageDevice_t*)Dev->Data;

					/* Validate parameters */

					/* Perform */
					if (Disk->Write(Disk->DiskData, Request->SectorLBA, Request->Buffer, Request->Length) != 0)
						Request->Status = RequestDeviceError;
					else
						Request->Status = RequestOk;
				}

			} break;

			default:
				break;
		}

		/* We are done, wakeup */
		SchedulerWakeupAllThreads((Addr_t*)Request);
	}
}
예제 #14
0
int isascii_l(int c, struct __locale_t *locale)
{
	_CRT_UNUSED(locale);
	return c >= 0 && c < 128;
}
예제 #15
0
void Nena::Application::Window::Initialize(
	_In_ Nena::Application::Window::Callback proc,
	_In_opt_ Nena::Application::Window::Boolean cursor
	)
{
	if (Raw) return;

	::OutputDebugStringA("Nena::Application::Window::Initialize()\n");

	Window::WindowClass wc;
	Window::ScreenSettings screen;

	::INT status = 0;
	::HMONITOR monitorHandle;
	::MONITORINFOEXA monitorInfo;

	status = FALSE;
	monitorHandle = NULL;
	ZeroMemory(&screen, sizeof Window::ScreenSettings);
	ZeroMemory(&wc, sizeof Window::WindowClass);

	// Setup windows class with default settings.
	wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
	wc.hbrBackground = (::HBRUSH)GetStockObject(BLACK_BRUSH);
	wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.cbSize = sizeof(WindowClass);
	wc.lpszClassName = Name.c_str();
	wc.lpszMenuName = NULL;
	wc.lpfnWndProc = proc;
	wc.hIconSm = wc.hIcon;
	wc.hInstance = Instance;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;

	// Register window class.
	auto atom = ::RegisterClassExA(&wc);

	if (atom == INVALID_ATOM)
	{
		auto error = GetLastError();
		return;
	}
	else status = TRUE;

	status = TRUE;
	POINT point = { 0 };

	// in the virtual screen space, primary display rect starts from (0, 0),
	// so it should return a handle to a default device
	monitorHandle = ::MonitorFromPoint(point, MONITOR_DEFAULTTOPRIMARY);
	if (monitorHandle == INVALID_HANDLE_VALUE || monitorHandle == NULL)
		OutputDebugStringA("\tFailed to get current monitor handle\n"),
		status = FALSE;
	ZeroMemory(&monitorInfo, sizeof MONITORINFOEXA);
	monitorInfo.cbSize = sizeof MONITORINFOEXA;
	if (status && !::GetMonitorInfoA(monitorHandle, &monitorInfo))
		OutputDebugStringA("\tFailed to get current monitor info\n"),
		status = FALSE;

	if (!status)
	{
		// an attempt to find monitor manually
		// or return the last one if ok
		status = EnumDisplayMonitors(NULL, NULL,
			(MONITORENUMPROC)[](
				HMONITOR monitor, HDC context,
				LPRECT rect, LPARAM data
				)
			{
				_CRT_UNUSED(context);
				((HMONITOR &) data) = monitor;
				if (rect->left == 0 && rect->top == 0) return FALSE;
				else return TRUE;
			},
			(LPARAM) (HMONITOR &) monitorHandle
			);

		if (status) status =
			monitorHandle != INVALID_HANDLE_VALUE &&
			monitorHandle != NULL;
	}

	if (status)
	{
		// current monitor was found
		ScreenWidth = (decltype(ScreenWidth)) (monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left);
		ScreenHeight = (decltype(ScreenHeight)) (monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top);
		X = (Int16) (monitorInfo.rcMonitor.left + (ScreenWidth - Width) / 2);
		Y = (Int16) (monitorInfo.rcMonitor.top + (ScreenHeight - Height) / 2);
	}
	else // all the attempts to find monitor device failed, try another approach
	{
		::ZeroMemory(&screen, sizeof ScreenSettings);
		if (!::EnumDisplaySettingsA(nullptr, ENUM_CURRENT_SETTINGS, &screen))
			OutputDebugStringA("\tFailed to get current display device\n"),
			status = FALSE,
			ScreenWidth = 0,
			ScreenHeight = 0;
		else
			ScreenWidth = (UInt16)screen.dmPelsWidth,
			ScreenHeight = (UInt16)screen.dmPelsHeight,
			X = (Int16)((ScreenWidth - Width) / 2),
			Y = (Int16)((ScreenHeight - Height) / 2);
	}

	if (Fullscreen) Raw = ::CreateWindowExA(
		WS_EX_APPWINDOW, Name.c_str(), Name.c_str(), Style,
		X, Y, ScreenWidth, ScreenHeight, nullptr, nullptr, Instance,
		nullptr
		);
	else Raw = ::CreateWindowExA(
		WS_EX_APPWINDOW, Name.c_str(), Name.c_str(), Style,
		X, Y, Width, Height, nullptr, nullptr, Instance,
		nullptr
		);

	if (Raw) // if window was created
	{
		::ShowWindow(Raw, SW_SHOW);
		::SetForegroundWindow(Raw);
		::SetFocus(Raw);
		::ShowCursor(cursor);

		// adjust window
		Fullscreen = !Fullscreen;
		ToggleFullscreen();
	}

	// notify a developer about window was created 
	// (or was not, should check a handle)
	Created(this);
}