For my first program, instead of "Hello world", I made a console application that allows you to type in the name of a DLL, and the console will load it and explicitly run a function named "Initiate" from the DLL. I have a DLL that creates a Win32 window, and it goes through the usual loop to keep the window alive. It seems to work great. I can even 'cout' messages to the console from the DLL, which is kinda cool.

So when I close the Win32 window, it frees the DLL and the console remains open, which has a goto statement to start over, and allow more input for another DLL. The problem that I am having, is that I want to be able to allow input to open another DLL right away. I'm assuming that the loop to keep the Win32 window open to proccess messages, is preventing the console from executing any further.

However, I'm not really sure how to approach this problem. Infact, the only way I was able to get as far as I did, is with Google. But now I'm not even really sure what search term to use. I don't really know much about threads, but that would be my best guess for this situation. Is that close, or far off?

Here is my code...

RunDLL: (console app to load DLL)
Code:
#include <iostream>
#include <string>
#include <windows.h>

std::string str_input;
typedef int (*INIT)(HWND, HINSTANCE, int);

int main()
{
	char t[500]; // Create var to hold title
	GetConsoleTitleA(t, 500); // Get title and assign to var
	HWND hwndConsole = FindWindowA( NULL, t ); // Assign HWND by search for title
	HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndConsole, GWL_HINSTANCE); // Get handle instance using HWND

	load: // LOAD SEQUENCE
	std::cout << "> ";
	std::cin >> str_input;

	if (str_input == TEXT("exit")) goto exit;

	HINSTANCE hInstLibrary = LoadLibrary(str_input.c_str());

	if (hInstLibrary)
	{
		INIT Initiate = (INIT)GetProcAddress(hInstLibrary, "Initiate");

		if (Initiate)
		{
			Initiate(hwndConsole, hInstance, SW_SHOWNORMAL);
		}

		FreeLibrary(hInstLibrary);
	}
	else
	{
		std::cout << "DLL failed to load" << std::endl;
	}

	goto load;

	exit: // EXIT SEQUENCE
	return 0;
}
DLL:
Code:
#include "windows.h"
#include <iostream>
#include <string>

extern "C"
{
	__declspec(dllexport) int Initiate(HWND, HINSTANCE, int);
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
void console_msg(std::string coutMsg);

extern "C"
{
//	DECLDIR int Initiate(HWND conhwnd, HINSTANCE hInstance, LPSTR lpszCmdLine, int nCmdShow)
	__declspec(dllexport) int Initiate(HWND conhwnd, HINSTANCE hInstance, int nCmdShow)
	{
		console_msg("Initiate called");

		WNDCLASS wc;
		wc.cbClsExtra = 0;
		wc.cbWndExtra = 0;
		wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
		wc.hCursor = LoadCursor( NULL, IDC_ARROW );
		wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
		wc.hInstance = hInstance;
		wc.lpfnWndProc = WndProc;
		wc.lpszClassName = TEXT("WinClass");
		wc.lpszMenuName = 0;
		wc.style = CS_HREDRAW | CS_VREDRAW;
		RegisterClass(&wc);

		HWND hwnd = CreateWindow(TEXT("WinClass"), TEXT("windows title"), WS_OVERLAPPEDWINDOW, 10, 10, 200, 200, NULL, NULL, hInstance, NULL );

		ShowWindow(hwnd, nCmdShow);
		UpdateWindow(hwnd);

		MSG msg;

		while(GetMessage(&msg, NULL, 0, 0))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}

		return msg.wParam;
	}
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
	switch( message )
	{
		case WM_CREATE:
			console_msg("Window created");
		break;
		case WM_PAINT:
		break;
		case WM_DESTROY:
			console_msg("Unloading library...");
			PostQuitMessage( 0 ) ;
			return 0;
		break;
	}

	return DefWindowProc( hwnd, message, wparam, lparam );
}

void console_msg(std::string coutMsg)
{
	std::cout << "DLL.dll> " << coutMsg << std::endl;
}
If anyone decides to compile this, compile it with character set "not set". That was a real pain to figure out. This conversation is open for any kind of suggestions or feedback, so please comment.

For RunDLL, I see a future problem I'm going to need to figure out.
Code:
		INIT Initiate = (INIT)GetProcAddress(hInstLibrary, "Initiate");

		if (Initiate)
		{
			Initiate(hwndConsole, hInstance, SW_SHOWNORMAL);
		}

		FreeLibrary(hInstLibrary);
It frees the library as soon as 'Initiate' is finished. I realize this, and I'm sure it's not a big deal as of right now...