Access violation during execution on CreateInstance function - c++

I'm setting a program to create a COM connection from an ocx file.
I'm using visual studio 2019 with debug x86. It correctly generate the .tlh and .tli files.
My failed tests:
Use visualtudio 2017 and 2019
Use CoCreateInstance:
IMachine* machine = NULL;
// this gives the same error:
HRESULT hr2 = CoCreateInstance(CLSID_Machine, NULL, CLSCTX_INPROC_SERVER,
IID_IMachine,
reinterpret_cast<LPVOID*>(&machine));
Replace CLSID_Machine by the _uuidof(IMachine)
Replace CLSID_Machine by the LPCWSTR clsidString
This is a part of my code:
#import "lib.ocx" no_namespace , named_guids
HRESULT hr1 = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
try {
if (SUCCEEDED(hr1))
{
IMachinePtr machineCUPtr;
HRESULT hr2 = machineCUPtr.CreateInstance(CLSID_Machine, NULL,
CLSCTX_INPROC_SERVER); //Failure
if (FAILED(hr2))
{
std::cout << "Fail:" << hr2 << std::endl;
}
else {
std::cout << "Success: " << hr2 << std::endl;
}
}
else {
std::cout << "Fail CoInit: " << std::endl;
}
}
catch (_com_error& e)
{
std::cout << "COM ERROR catched " << std::endl;
std::cout << "Code = %08lx\n" << e.Error() << std::endl;
std::cout << "Meaning = %s\n" << e.ErrorMessage() << std::endl;
std::cout << "Source = %s\n" << (LPCSTR)e.Source() << std::endl;
std::cout << "Description = %s\n" << (LPCSTR)e.Description() << std::endl;
}
CoUninitialize();
}
I still have this error:
Exception raised to 0x00B20768 in myApp.exe : 0xC000000005 : Access
violation during execution at location 0x00B20768.
Edit:
'''
#include <iostream>
#import "libcom.ocx"
using namespace LIBCOM;
int main()
{
CoInitialize(NULL);
IMachinePtr machineCUPtr(__uuidof(Machine)); //Same error
machineCUPtr->MyMethod(parameters of the method);
CoUninitialize();
return 0;
}
''''

Related

Why do EnumDomains/NextDomain loop forever?

The following simple code can be directly run in Visual Studio C++ console project.
It will loop forever because the NextDomain will always return the same IUnknown *
According to Microsoft, it should return NULL if the enumeration reaches end. See https://learn.microsoft.com/en-us/dotnet/framework/unmanaged-api/hosting/icorruntimehost-nextdomain-method
However, the NULL is never reached. It seems that it never return the NextDomain but keep returning the same domain.
Is there anything wrong? Thanks.
#include <iostream>
#include <Windows.h>
#include <metahost.h>
#include <mscoree.h>
#pragma comment(lib, "mscoree.lib")
int main()
{
ICLRMetaHost* clrMetaHost = NULL;
ICLRRuntimeInfo* clrRuntimeInfo = NULL;
ICorRuntimeHost* clrCorRuntimeHost = NULL;
do {
if (FAILED(CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&clrMetaHost))))
{
std::cout << "failed 1" << std::endl;
break;
}
if (FAILED(clrMetaHost->GetRuntime(L"v2.0.50727", IID_PPV_ARGS(&clrRuntimeInfo))))
{
if (FAILED(clrMetaHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&clrRuntimeInfo))))
{
std::cout << "failed 2" << std::endl;
break;
}
}
if (FAILED(clrRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_PPV_ARGS(&clrCorRuntimeHost))))
{
std::cout << "failed 3" << std::endl;
break;
}
if (FAILED(clrCorRuntimeHost->Start()))
{
std::cout << "failed 4" << std::endl;
break;
}
HDOMAINENUM hDomainEnum = nullptr;
if (FAILED(clrCorRuntimeHost->EnumDomains(&hDomainEnum))) {
std::cout << "failed 5" << std::endl;
break;
}
IUnknown* domain;
while (SUCCEEDED(clrCorRuntimeHost->NextDomain(hDomainEnum, &domain))
&& domain != NULL) {
std::cout << "why loop forever here?" << std::endl;
domain->Release();
}
if (FAILED(clrCorRuntimeHost->CloseEnum(hDomainEnum))) {
std::cout << "failed 6" << std::endl;
}
break;
} while (0);
if (clrCorRuntimeHost != NULL) clrCorRuntimeHost->Release();
if (clrRuntimeInfo != NULL) clrRuntimeInfo->Release();
if (clrMetaHost != NULL) clrMetaHost->Release();
return 0;
}
Return code from most enumerators is S_OK to continue and S_FALSE when it did not succeed. S_FALSE is not a fail code.
while (S_OK == clrCorRuntimeHost->NextDomain(hDomainEnum, &domain))
&& domain != NULL) {
std::cout << "why loop forever here?" << std::endl;
domain->Release();
}

How to get the process ID when starting Mozilla Firefox?

The task of getting the PID of the process that I'm starting, CreateProcess() ProcessInformation.dwProcessId does a great job of this, but in my case, the process that I start opens the child processes and then closes, and I need to get all the PIDs that creates the process I am opening.
I found this code, it receives the child PIDs but they do not match the final Firefox window, what am I doing wrong
Source:
CreateProcess returns handle different than launched Chrome.exe
Update 1
After Drake Wu - MSFT comment, I used the following code
int test(const wchar_t* programPath) {
HANDLE Job = CreateJobObject(nullptr, nullptr);
if (!Job) {
std::cout << "CreateJobObject, error " << GetLastError() << std::endl;
return 0;
}
HANDLE IOPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 1);
if (!IOPort) {
std::cout << "CreateIoCompletionPort, error " << GetLastError() << std::endl;
return 0;
}
JOBOBJECT_ASSOCIATE_COMPLETION_PORT Port;
Port.CompletionKey = Job;
Port.CompletionPort = IOPort;
if (!SetInformationJobObject(Job,
JobObjectAssociateCompletionPortInformation,
&Port, sizeof(Port))) {
std::cout << "SetInformation, error " << GetLastError() << std::endl;
return 0;
}
PROCESS_INFORMATION ProcessInformation;
STARTUPINFOW StartupInfo = { sizeof(StartupInfo) };
LPWSTR szCmdline = const_cast<LPWSTR>(programPath);
if (!CreateProcessW(
programPath,
nullptr,
nullptr,
nullptr,
FALSE,
CREATE_SUSPENDED,
nullptr,
nullptr,
&StartupInfo,
&ProcessInformation))
{
std::cout << "CreateProcess, error " << GetLastError() << std::endl;
return 0;
}
std::cout << "PID: " << ProcessInformation.dwProcessId << std::endl;
if (!AssignProcessToJobObject(Job, ProcessInformation.hProcess)) {
std::cout << "Assign, error " << GetLastError() << std::endl;
return 0;
}
ResumeThread(ProcessInformation.hThread);
CloseHandle(ProcessInformation.hThread);
CloseHandle(ProcessInformation.hProcess);
DWORD CompletionCode;
ULONG_PTR CompletionKey;
LPOVERLAPPED Overlapped;
while (GetQueuedCompletionStatus(IOPort, &CompletionCode, &CompletionKey, &Overlapped, INFINITE))
{
switch (CompletionCode)
{
case JOB_OBJECT_MSG_NEW_PROCESS:
std::cout << "New PID: " << (int)Overlapped << std::endl;
break;
case JOB_OBJECT_MSG_EXIT_PROCESS:
std::cout << "Exit PID: " << (int)Overlapped << std::endl;
break;
case JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO:
std::cout << "JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO" << std::endl;
break;
default:
break;
}
if (CompletionCode == JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO)
break;
}
std::cout << "All done" << std::endl;
}
and I got the following results:
standart Firefox
test(L"C:\\Program Files\\Mozilla Firefox\\firefox.exe");
portable edition Firefox
test(L"D:\\FirefoxPortable\\FirefoxPortable.exe");
As before, PIDs are incorrectly returned. In the case of the portable version, the process hangs on the while loop, in the case of the standard version of firefox, GetQueuedCompletionStatus() returns JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO. Why am I getting the wrong result?
Update 2
I ran Visual Studio as an administrator and, but on standard startup everything displays correctly
I tested that the process of Firefox is not new and exit in order(the pid obtained by CreateProcess will exit), and your code will not receive the new Firefox process if there is any new process created later.
You could use swtich-case statement, the following sample work for me:
int openProgram(const wchar_t* programPath) {
HANDLE Job = CreateJobObject(nullptr, nullptr);
if (!Job) {
std::cout << "CreateJobObject, error " << GetLastError() << std::endl;
return 0;
}
HANDLE IOPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 1);
if (!IOPort) {
std::cout << "CreateIoCompletionPort, error " << GetLastError() << std::endl;
return 0;
}
JOBOBJECT_ASSOCIATE_COMPLETION_PORT Port;
Port.CompletionKey = Job;
Port.CompletionPort = IOPort;
if (!SetInformationJobObject(Job,
JobObjectAssociateCompletionPortInformation,
&Port, sizeof(Port))) {
std::cout << "SetInformation, error " << GetLastError() << std::endl;
return 0;
}
PROCESS_INFORMATION ProcessInformation;
STARTUPINFO StartupInfo = { sizeof(StartupInfo) };
LPTSTR szCmdline = _tcsdup(programPath);
if (!CreateProcessW(
nullptr,
szCmdline,
nullptr,
nullptr,
FALSE,
CREATE_SUSPENDED,
nullptr,
nullptr,
&StartupInfo,
&ProcessInformation))
{
std::cout << "CreateProcess, error " << GetLastError() << std::endl;
return 0;
}
std::cout << "PID: " << ProcessInformation.dwProcessId << std::endl;
if (!AssignProcessToJobObject(Job, ProcessInformation.hProcess)) {
std::cout << "Assign, error " << GetLastError() << std::endl;
return 0;
}
ResumeThread(ProcessInformation.hThread);
CloseHandle(ProcessInformation.hThread);
CloseHandle(ProcessInformation.hProcess);
DWORD CompletionCode;
ULONG_PTR CompletionKey;
LPOVERLAPPED Overlapped;
while (GetQueuedCompletionStatus(IOPort, &CompletionCode, &CompletionKey, &Overlapped, INFINITE))
{
switch (CompletionCode)
{
case JOB_OBJECT_MSG_NEW_PROCESS:
std::cout << "New PID: " << (int)Overlapped << std::endl;
break;
case JOB_OBJECT_MSG_EXIT_PROCESS:
std::cout << "Exit PID: " << (int)Overlapped << std::endl;
break;
case JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO:
std::cout << "JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO" << std::endl;
break;
default:
break;
}
if (CompletionCode == JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO)
break;
}
std::cout << "All done" << std::endl;
}
Result:

System.NullReferenceException object reference not set to an instance

I'm a beginner with C++. In my code, I am trying to get a list of the updates installed on the machine.
In my machine 1, I'm using Windows 7, and the code work perfectly. But in machine 2, using Windows 7 too, I get the error.
I don't understand enough to know what actually needs fixing, or how to fix it.
My program stops working with the below code, and displays this error:
unhandled exception system.NullReferenceException object reference not set to an instance
try
{
HRESULT hr;
hr = CoInitialize(NULL);
IUpdateSession* iUpdate;
IUpdateSearcher* searcher;
ISearchResult* results;
BSTR criteria = SysAllocString(L"IsInstalled=0 or IsHidden=1 or IsPresent=1");
hr = CoCreateInstance(CLSID_UpdateSession, NULL, CLSCTX_INPROC_SERVER, IID_IUpdateSession, (LPVOID*)&iUpdate);
hr = iUpdate->CreateUpdateSearcher(&searcher);
//wcout << L"Searching for updates ..." << endl;
hr = searcher->Search(criteria, &results);
SysFreeString(criteria);
switch (hr)
{
case S_OK:
//wcout << L"List of applicable items on the machine:" << endl;
break;
case WU_E_LEGACYSERVER:
wcout << L"No server selection enabled" << endl;
case WU_E_INVALID_CRITERIA:
wcout << L"Invalid search criteria" << endl;
}
IUpdateCollection *updateList;
IUpdate *updateItem;
LONG updateSize = 0;
LONG totalKB = 0;
results->get_Updates(&updateList);
updateList->get_Count(&updateSize);
if (updateSize == 0)
{
//wcout << L"No updates found" << endl;
}
for (LONG i = 0; i < updateSize; i++)
{
IStringCollection *KBCollection;
BSTR updateName;
LONG KBCount;
updateList->get_Item(i, &updateItem);
updateItem->get_Title(&updateName);
USES_CONVERSION;
//outputFile << W2A(CString(updateName)) << " --- ";
updateItem->get_KBArticleIDs(&KBCollection);
KBCollection->get_Count(&KBCount);
for (int i = 0; i<KBCount; i++)
{
BSTR KBValue;
totalKB += 1;
KBCollection->get_Item(i, &KBValue);
USES_CONVERSION;
//std::string strk = streamkb.str();
file << "{" << endl;
std::stringstream ss;
ss << W2A(CString("KB")) << W2A(CString(KBValue));
std::string s = ss.str();
list2.push_back(s);
file << "\"Correctif" << totalKB << "\": \"" << W2A(CString("KB")) << W2A(CString(KBValue)) << "\"" << endl;
file << "}," << endl;
}
}
::CoUninitialize();
}
catch (const std::exception & ex)
{
}

Fake files "exist" after checking real files?

I have been programming C++ on Linux for a while, but recently moved to a windows 10 computer.
I managed to set up CodeBlocks with w64-mingw.
I have been trying to move programs from linux to windows and I'm having trouble with filenames. For example, I have code to check if files or directories exist, and to create directories. But I get weird results, if a file check comes back as true, then all subsequent file checks come back as true. I have example code, where test.txt and testdir are a file and directory that do not initially exist, but are created by the program. fail.txt and faildir never exist, but my program claims they exist AFTER creating test.txt and testdir. I've seen several questions about checking if files exist on Windows, but I've never run into behavior like this, and I'm not sure what's going on. Does windows fail to reinitialize something when GetFileAttributes() is called? Or have I missed something really basic?
main.cpp
#include <iostream>
#include <fstream>
#include "../include/FileChecker.h"
int main(){
FileChecker fc = FileChecker();
std::cout << "Test Start" << std::endl;
#ifdef _WIN32
std::cout << "OS is windows" << std::endl;
#endif // _WIN32
std::cout << std::endl;
std::cout << "Nothing should exist" << std::endl;
if(fc.file_exists("test.txt")){
std::cout << "test.txt exists." << std::endl;
}else{
std::cout << "test.txt does not exist." << std::endl;
}
if(fc.file_exists("fail.txt")){
std::cout << "fail.txt exists." << std::endl;
}else{
std::cout << "fail.txt does not exist." << std::endl;
}
if(fc.directory_exists("testdir")){
std::cout << "Directory testdir exists." << std::endl;
}else{
std::cout << "Directory testdir does not exist." << std::endl;
}
if(fc.directory_exists("faildir")){
std::cout << "Directory faildir exists." << std::endl;
}else{
std::cout << "Directory faildir does not exist." << std::endl;
}
std::cout << std::endl;
std::cout << "Creating test.txt" << std::endl;
std::ofstream test("test.txt");
test << "HELLO" << std::endl;
test.close();
std::cout << "Only test.txt should exist" << std::endl;
if(fc.file_exists("test.txt")){
std::cout << "test.txt exists." << std::endl;
}else{
std::cout << "test.txt does not exist." << std::endl;
}
if(fc.file_exists("fail.txt")){
std::cout << "fail.txt exists." << std::endl;
}else{
std::cout << "fail.txt does not exist." << std::endl;
}
if(fc.directory_exists("testdir")){
std::cout << "Directory testdir exists." << std::endl;
}else{
std::cout << "Directory testdir does not exist." << std::endl;
}
if(fc.directory_exists("faildir")){
std::cout << "Directory faildir exists." << std::endl;
}else{
std::cout << "Directory faildir does not exist." << std::endl;
}
std::cout << std::endl;
std::cout << "Creating directory testdir" << std::endl;
if(fc.create_directory("testdir")){
std::cout << "Creation Success" << std::endl;
}else{
std::cout << "Creation Failed" << std::endl;
}
std::cout << "Only testdir should exist" << std::endl;
if(fc.directory_exists("testdir")){
std::cout << "Directory testdir exists." << std::endl;
}else{
std::cout << "Directory testdir does not exist." << std::endl;
}
if(fc.directory_exists("faildir")){
std::cout << "Directory faildir exists." << std::endl;
}else{
std::cout << "Directory faildir does not exist." << std::endl;
}
return 0;
}
FileChecker.h
#ifndef FILECHECKER_H
#define FILECHECKER_H
#ifdef _WIN32
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <direct.h>
#endif // _WIN32
#include <string>
class FileChecker
{
public:
FileChecker();
virtual ~FileChecker();
bool file_exists(std::string filename);
bool directory_exists(std::string dirname);
bool create_file(std::string filename);
bool create_directory(std::string dirname);
protected:
private:
};
#endif // FILECHECKER_H
FileChecker.cpp
#include "../include/FileChecker.h"
FileChecker::FileChecker(){
//ctor
}
FileChecker::~FileChecker(){
//dtor
}
#ifdef _WIN32
bool FileChecker::file_exists(std::string filename){
static LPCTSTR szPath = TEXT(filename.c_str());
DWORD dwAttrib = GetFileAttributes(szPath);
return ((dwAttrib != INVALID_FILE_ATTRIBUTES) && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
#endif // _WIN32
#ifdef _WIN32
bool FileChecker::directory_exists(std::string dirname){
static LPCTSTR szPath = TEXT(dirname.c_str());
DWORD dwAttrib = GetFileAttributes(szPath);
return ((dwAttrib != INVALID_FILE_ATTRIBUTES) && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
#endif // _WIN32
#ifdef _WIN32
bool FileChecker::create_directory(std::string dirname){
static LPCTSTR szPath = TEXT(dirname.c_str());
return(CreateDirectory(szPath, NULL));
}
#endif // _WIN32
Output
You should remove all static keyword in your functions.
bool FileChecker::file_exists(std::string filename){
static LPCTSTR szPath = TEXT(filename.c_str()); // <--- [*]
DWORD dwAttrib = GetFileAttributes(szPath);
when file_exists function is called first time, szPath variable is created and initialized pointing to array of characters of filename. When you call file_exists second time, value of szPath is still the same, and points to invalid data (keeps pointer to data of filename object, which was deleted after calling file_exists first time).
You should read about static variables in functions.
Your code here:
bool FileChecker::file_exists(std::string filename){
static LPCTSTR szPath = TEXT(filename.c_str());
DWORD dwAttrib = GetFileAttributes(szPath);
return ((dwAttrib != INVALID_FILE_ATTRIBUTES) && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
TEXT simply casts, it does not perform any sort of conversion. Make it the following instead:
bool FileChecker::file_exists(std::string filename)
{
DWORD dwAttrib = GetFileAttributesA(filename.c_str());
return ((dwAttrib != INVALID_FILE_ATTRIBUTES) && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}

OpenCL Child Kernel Error

Aloha,
I'm struggling with OpenCL child kernel feature.
Kernel SRC (Minimal example):
kernel void launcher()
{
ndrange_t ndrange = ndrange_1D(1);
enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange,
^{
size_t id = get_global_id(0);
}
);
}
stdafx.h:
#pragma once
#define __CL_ENABLE_EXCEPTIONS
#define CL_HPP_ENABLE_EXCEPTIONS
#define CL_HPP_TARGET_OPENCL_VERSION 200
#include "targetver.h"
#include <CL/cl2.hpp>
#include <iostream>
#include <string>
Full SRC (Minimal):
#include "stdafx.h"
std::string kernel2_source(
"kernel void launcher() ""\n"
"{ ""\n"
" ndrange_t ndrange = ndrange_1D(1);""\n"
" enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange,""\n"
" ^{""\n"
" size_t id = get_global_id(0);""\n"
" }""\n"
" );""\n"
"}""\n");
//Number of Input Elements
constexpr int numTriangles = 10;
cl_int errorcode = CL_BUILD_ERROR; //Has to be set to build error, because errorcode isn't set when exception occurs
//Move variable definitions out of main for test purposes;
//Numerous definitions
cl::Program program;
std::vector<cl::Device> devices;
std::vector<cl::Platform> platforms;
cl::CommandQueue queue;
cl::Program::Sources source{ kernel2_source };
int main() {
try {
// Query for platforms
cl::Platform::get(&platforms);
std::cout << "Num Platforms: " << platforms.size() << std::endl;
// Get a list of devices on this platform
platforms[0].getDevices(CL_DEVICE_TYPE_ALL, &devices);
std::cout << "Using platform: " << platforms[0].getInfo<CL_PLATFORM_NAME>() << std::endl;
std::cout << "Num Devices: " << devices.size() << std::endl;
// Create a context for the devices
std::cout << "Using device: " << devices[0].getInfo<CL_DEVICE_NAME>() << std::endl;
//Create a context for the first device
//cl::Context context({ devices[0]});
cl::Context context({ devices[0] });
// Create a command−queue for the first device
queue = cl::CommandQueue(context, devices[0]);
cl::DeviceCommandQueue deviceQueue;
deviceQueue = cl::DeviceCommandQueue(context, devices[0]);
// Create the program from the source code
program = cl::Program(context, source);
std::cout << "Building Program" << std::endl;
// Build the program for the devices
errorcode = program.build("-cl-std=CL2.0 -g");
std::cout << "Success!" << std::endl;
cl::Kernel kernel = cl::Kernel(program, "launcher");
cl::NDRange global = numTriangles;
cl::NDRange local = 1;
queue.enqueueNDRangeKernel(kernel, cl::NullRange, global, local);
std::cout << "finished" << std::endl;
std::cin.get();
}
catch (cl::Error error)
{
std::cout << "Error!" << std::endl;
std::cout << error.what() << "(" << error.err() << ")" << std::endl;
std::cout << "Errorcode: " << errorcode << std::endl;
if (errorcode != CL_SUCCESS) { //...
std::cout << "Build Status: " << program.getBuildInfo<CL_PROGRAM_BUILD_STATUS>(devices[0]) << std::endl;
//std::cout << "Build Status: " << program.getBuildInfo<CL_PROGRAM_BUILD_STATUS>(devices[1]) << std::endl;
std::cout << "Build Options:" << program.getBuildInfo<CL_PROGRAM_BUILD_OPTIONS>(devices[0]) << std::endl;
//std::cout << "Build Options:" << program.getBuildInfo<CL_PROGRAM_BUILD_OPTIONS>(devices[1]) << std::endl;
std::cout << "Build Log:" << program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(devices[0]) << std::endl;
//std::cout << "Build Log:" << program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(devices[1]) << std::endl;
}
}
std::cin.get();
return 0;
}
Output:
Num Platforms: 1
Using platform: AMD Accelerated Parallel Processing
Num Devices: 2
Using device: Hawaii
Building Program
=> Exception.
There appears an uncaught exception which is strange, because all build error should be caught.
The ndrange_1D(1) is just for testing purposes (and to produce an acceptable amount of dummy output).
The device (AMD R9 390X) is OpenCL 2.0 capable.
Any ideas how to fix this?
EDIT:
Even not using exceptions and using errorcodes throws this an exception!