Skip to content

Instantly share code, notes, and snippets.

@TheVice
Created November 10, 2016 21:46
Show Gist options
  • Save TheVice/3aae5d453bc79fde13c844e0877e6575 to your computer and use it in GitHub Desktop.
Save TheVice/3aae5d453bc79fde13c844e0877e6575 to your computer and use it in GitHub Desktop.
Instance limiter (WIN32) - threre was a task to make library that control count of app count on local PC and via local network. As reference used https://msdn.microsoft.com/en-us/library/windows/desktop/ms686701(v=vs.85).aspx (local PC) and https://web.archive.org/web/20140131015856/http://www.xakep.ru/magazine/xa/048/087/1.asp (work with sockec…
cmake_minimum_required(VERSION 2.8.12)
project("test_task")
# library
set(library_root ${CMAKE_CURRENT_SOURCE_DIR}/library)
file(GLOB_RECURSE SRC_Files ${library_root}/*.h ${library_root}/*.c ${library_root}/*.cpp)
add_library(library SHARED ${SRC_Files})
# demo_stand-alone
set(demo_stand-alone_root ${CMAKE_CURRENT_SOURCE_DIR}/demo_stand-alone)
file(GLOB_RECURSE SRC_Files ${demo_stand-alone_root}/*.h ${demo_stand-alone_root}/*.c ${demo_stand-alone_root}/*.cpp)
add_executable(demo_stand-alone WIN32 ${SRC_Files})
target_link_libraries(demo_stand-alone library)
# demo_network
set(demo_network_root ${CMAKE_CURRENT_SOURCE_DIR}/demo_network)
file(GLOB_RECURSE SRC_Files ${demo_network_root}/*.h ${demo_network_root}/*.c ${demo_network_root}/*.cpp)
add_executable(demo_network ${SRC_Files})
target_link_libraries(demo_network library)
#include "../library/library.h"
#include <tchar.h>
int _tmain(int argc, _TCHAR *argv[])
{
if (argc > 1)
{
onThreadCreateAtNetwork(argv[1]);
}
else
{
onThreadCreateAtNetwork(nullptr);
}
return 0;
}
#include "../library/library.h"
#include <windows.h>
#include <tchar.h>
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
(void)hInstance;
(void)hPrevInstance;
(void)lpCmdLine;
(void)nCmdShow;
//
onThreadCreate();
return 0;
}
#include "library.h"
#include <windows.h>
#include <TlHelp32.h>
#include <tchar.h>
#include <stdio.h>
#pragma comment(lib, "WSock32")
static const long gMaxInstanceCount = 2;
static long gInstanceCount = 0;
static char gModulePath[MAX_MODULE_NAME32 + 1];
bool isModulesLoadByProcess(DWORD pid)
{
HANDLE processSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
if (processSnap == INVALID_HANDLE_VALUE)
{
return false;
}
MODULEENTRY32 me32;
memset(&me32, 0, sizeof(me32));
me32.dwSize = sizeof(me32);
if (!Module32First(processSnap, &me32))
{
CloseHandle(processSnap);
return false;
}
do
{
if (!lstrcmpA(gModulePath, me32.szExePath))
{
CloseHandle(processSnap);
return true;
}
} while (Module32Next(processSnap, &me32));
CloseHandle(processSnap);
return false;
}
void listProcess()
{
HANDLE processSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (processSnap == INVALID_HANDLE_VALUE)
{
return;
}
PROCESSENTRY32 pe32;
memset(&pe32, 0, sizeof(pe32));
pe32.dwSize = sizeof(pe32);
if (!Process32First(processSnap, &pe32))
{
CloseHandle(processSnap);
return;
}
do
{
if (pe32.th32ProcessID == 0)
{
continue;
}
gInstanceCount += isModulesLoadByProcess(pe32.th32ProcessID) ? 1 : 0;
} while (Process32Next(processSnap, &pe32));
CloseHandle(processSnap);
}
void fillModulePath()
{
STARTUPINFO startupInfo;
memset(&startupInfo, 0, sizeof(startupInfo));
startupInfo.cb = sizeof(startupInfo);
GetStartupInfo(&startupInfo);
char* lastSlash = strrchr(startupInfo.lpTitle, '\\');
if (lastSlash)
{
size_t length = lastSlash - startupInfo.lpTitle + 1;
strncpy(gModulePath, startupInfo.lpTitle, length);
strcat(gModulePath, "library.dll");
}
else
{
sprintf(gModulePath, "%s\\library.dll", startupInfo.lpTitle);
}
}
__declspec(dllexport) void __stdcall onThreadCreate()
{
fillModulePath();
listProcess();
TCHAR message[MAX_PATH];
if (gInstanceCount <= gMaxInstanceCount)
{
_stprintf(message, TEXT("There is a %ld hinstance of a program.\r\nTo stop current hinstance press OK button below."), gInstanceCount);
MessageBox(HWND_DESKTOP, message, TEXT("demo_stand-alone"), MB_OK);
}
else
{
_stprintf(message, TEXT("Reached maximum count of application instances - %ld.\r\nPress OK to exit."), gMaxInstanceCount);
MessageBox(HWND_DESKTOP, message, TEXT("demo_stand-alone"), MB_ICONWARNING);
}
}
//#define PRINT_NET_STATIC 1
void client(const char* address, char command)
{
BOOL allow = -1;
int err = 0;
WSADATA wsaData;
if (!(err = WSAStartup(MAKEWORD(2, 0), &wsaData)))
{
SOCKADDR_IN rmaddr;
memset(&rmaddr, 0, sizeof(rmaddr));
rmaddr.sin_addr.s_addr = inet_addr(address);
rmaddr.sin_family = AF_INET;
rmaddr.sin_port = htons(7766);
SOCKET send_sock = socket(AF_INET, SOCK_STREAM, 0);
if (INVALID_SOCKET != send_sock)
{
err = connect(send_sock, (struct sockaddr *)&rmaddr, sizeof(rmaddr));
if (SOCKET_ERROR != err)
{
char message[2 + sizeof(long)];
int length = sizeof(message) / sizeof(*message);
if ('a' == command)
{
sprintf(message, "a%d", gInstanceCount + 1);
err = send(send_sock, message, length, 0);
if (SOCKET_ERROR != err)
{
err = recv(send_sock, message, length, 0);
if (SOCKET_ERROR != err)
{
if ('1' == message[0])
{
#ifdef PRINT_NET_STATIC
fprintf(stdout, "Allow");
#endif
gInstanceCount = atol(&message[1]);
allow = TRUE;
}
else
{
#ifdef PRINT_NET_STATIC
fprintf(stdout, "Not allow");
#endif
allow = FALSE;
}
}
else
{
fprintf(stderr, "recv failed with error: %d\n", err);
}
}
else
{
fprintf(stderr, "send failed with error: %d\n", err);
}
}
else if ('-' == command)
{
sprintf(message, "-");
err = send(send_sock, message, length, 0);
if (SOCKET_ERROR == err)
{
fprintf(stderr, "send failed with error: %d\n", err);
}
Sleep(500);
}
}
else
{
fprintf(stderr, "Unable to established connection with: %s (error %i)\n", address, err);
}
}
else
{
fprintf(stderr, "socket failed with error: %lld\n", send_sock);
}
WSACleanup();
}
else
{
fprintf(stderr, "WSAStartup failed with error: %d\n", err);
}
TCHAR message[MAX_PATH];
if (TRUE == allow)
{
_stprintf(message, TEXT("There is a %d hinstance of a program.\r\nTo stop current hinstance press OK button below."), gInstanceCount);
MessageBox(HWND_DESKTOP, message, TEXT("demo_stand-alone"), MB_OK);
Sleep(500);
client(address, '-');
}
else if (!allow)
{
_stprintf(message, TEXT("Reached maximum count of application instances - %d.\r\nPress OK to exit."), gMaxInstanceCount);
MessageBox(HWND_DESKTOP, message, TEXT("demo_stand-alone"), MB_ICONWARNING);
}
}
void server()
{
int err = 0;
WSADATA wsaData;
if (!(err = WSAStartup(MAKEWORD(2, 2), &wsaData)))
{
SOCKET listet_sock = socket(AF_INET, SOCK_STREAM, 0);
if (INVALID_SOCKET != listet_sock)
{
SOCKADDR_IN addr_sock;
memset(&addr_sock, 0, sizeof(addr_sock));
addr_sock.sin_family = AF_INET;
addr_sock.sin_addr.s_addr = htonl(INADDR_ANY);
addr_sock.sin_port = htons(7766);
if (bind(listet_sock, (LPSOCKADDR)&addr_sock, sizeof(struct sockaddr)))
{
fprintf(stderr, "Unable to bind to socket");
return;
}
if (listen(listet_sock, 1))
{
fprintf(stderr, "Unable to listen socket");
return;
}
while (true)
{
SOCKET send_sock = accept(listet_sock, nullptr, nullptr);
if (INVALID_SOCKET == send_sock)
{
fprintf(stderr, "socket failed with error: %lld\n", send_sock);
break;
}
while (true)
{
char message[2 + sizeof(long)];
int length = sizeof(message) / sizeof(*message);
err = recv(send_sock, message, length, 0);
if ((SOCKET_ERROR == err) || (0 == err))
{
err = WSAGetLastError();
break;
}
if ('a' == message[0])
{
#ifdef PRINT_NET_STATIC
sockaddr s;
length = sizeof(s);
if (SOCKET_ERROR != getpeername(send_sock, &s, &length))
{
fprintf(stdout, "%s have %s\n", inet_ntoa(((sockaddr_in*)(&s))->sin_addr), &message[1]);
}
#endif
long lMessage = atol(&message[1]);
if (gInstanceCount + lMessage <= gMaxInstanceCount)
{
sprintf(message, "1%d", gInstanceCount + lMessage);
}
else
{
sprintf(message, "0");
}
err = send(send_sock, message, length, 0);
if (SOCKET_ERROR == err)
{
fprintf(stderr, "send failed with error: %d\n", err);
}
else
{
if (gInstanceCount + lMessage <= gMaxInstanceCount)
{
gInstanceCount += lMessage;
}
}
}
else if ('-' == message[0])
{
if (gInstanceCount > 0)
{
--gInstanceCount;
}
}
}
shutdown(send_sock, 1);
closesocket(send_sock);
}
}
else
{
fprintf(stderr, "socket failed with error: %lld\n", listet_sock);
}
WSACleanup();
}
else
{
fprintf(stderr, "WSAStartup failed with error: %d\n", err);
}
}
__declspec(dllexport) void __stdcall onThreadCreateAtNetwork(const char* server_address)
{
if (nullptr == server_address)
{
server();
}
else
{
client(server_address, 'a');
}
}
#ifndef __LIBRARY_H__
#define __LIBRARY_H__
__declspec(dllexport) void __stdcall onThreadCreate();
__declspec(dllexport) void __stdcall onThreadCreateAtNetwork(const char* server_address);
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment