Again me posting the whole code
Sorry again, but I don't know where the mistake is?
This program uses a DLL and in DLL it (should) stores a string, that user has entered. DLL keeps this data in shared memory, so (like Author in the book which I'm currently reading and from which is the example, writes) every instance of the the same (this) program, should have access ti this shared memory.
From strange reasons, I can run multiple instances of the program (and add or delete previously stored strings) but single instance cannot see (have access) other strings that other instance entered, and vise-versa (which it should be the point of working with this kind of DLL).
Compiler gives no warning or errors in report.
This is the whole program:
#include <windows.h>
#include <wchar.h>
#include "strlib.h"
#pragma data_seg ("shared")
int iTotal = 0;
WCHAR szStrings[MAX_STRINGS][MAX_LENGTH + 1] = { '\0' };
#pragma data_seg ()
#pragma comment(linker, "/SECTION:shared, RWS")
int WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
{
return TRUE;
}
EXPORT BOOL CALLBACK AddStringA(PCSTR pStringIn)
{
BOOL bReturn;
int iLength;
PWSTR pWideStr;
iLength = MultiByteToWideChar(CP_ACP, 0, pStringIn, -1, NULL, 0);
pWideStr = malloc(iLength);
MultiByteToWideChar(CP_ACP, 0, pStringIn, -1, pWideStr, iLength);
bReturn = AddStringW(pWideStr);
free(pWideStr);
return bReturn;
}
EXPORT BOOL CALLBACK AddStringW(PCWSTR pStringIn)
{
PWSTR pString;
int i, iLength;
if (iTotal == MAX_STRINGS - 1)
return FALSE;
if ((iLength = wcslen(pStringIn)) == 0)
return FALSE;
pString = malloc(sizeof (WCHAR) * (1 + iLength));
wcscpy(pString, pStringIn);
_wcsupr(pString);
for (i = iTotal; i > 0; i--)
{
if (wcscmp(pString, szStrings[i - 1]) >= 0)
break;
wcscpy(szStrings[i], szStrings[i - 1]);
}
wcscpy(szStrings[i], pString);
iTotal++;
free(pString);
return TRUE;
}
EXPORT BOOL CALLBACK DeleteStringA(PCSTR pStringIn)
{
BOOL bReturn;
int iLength;
PWSTR pWideStr;
iLength = MultiByteToWideChar(CP_ACP, 0, pStringIn, -1, NULL, 0);
pWideStr = malloc(iLength);
MultiByteToWideChar(CP_ACP, 0, pStringIn, -1, pWideStr, iLength);
bReturn = DeleteStringW(pWideStr);
free(pWideStr);
return bReturn;
}
EXPORT BOOL CALLBACK DeleteStringW(PCWSTR pStringIn)
{
int i, j;
if (0 == wcslen(pStringIn))
return FALSE;
for (i = 0; i < iTotal; i++)
if (_wcsicmp(szStrings[i], pStringIn) == 0)
break;
if (i == iTotal)
return FALSE;
for (j = i; j < iTotal; j++)
wcscpy(szStrings[j], szStrings[j + 1]);
szStrings[iTotal--][0] = '\0';
return TRUE;
}
EXPORT int CALLBACK GetStringsA(GETSTRCB pfnGetStrCallBack, PVOID pParam)
{
BOOL bReturn;
int i, iLength;
PSTR pAnsiStr;
for (i = 0; i < iTotal; i++)
{
iLength = WideCharToMultiByte(CP_ACP, 0, szStrings[i], -1, NULL, 0, NULL, NULL);
pAnsiStr = malloc(iLength);
WideCharToMultiByte(CP_ACP, 0, szStrings[i], -1, pAnsiStr, iLength, NULL, NULL);
bReturn = pfnGetStrCallBack(pAnsiStr, pParam);
if (bReturn == FALSE)
return i + 1;
free(pAnsiStr);
}
return iTotal;
}
EXPORT int CALLBACK GetStringsW(GETSTRCB pfnGetStrCallBack, PVOID pParam)
{
BOOL bReturn;
int i;
for (i = 0; i < iTotal; i++)
{
bReturn = pfnGetStrCallBack(szStrings[i], pParam);
if (bReturn == FALSE)
return i + 1;
}
return iTotal;
}
#ifdef __cplusplus
#define EXPORT extern "C" __declspec (dllexport)
#else
#define EXPORT __declspec (dllexport)
#endif
#define MAX_STRINGS 256
#define MAX_LENGTH 63
typedef BOOL (CALLBACK * GETSTRCB) (PCTSTR, PVOID);
EXPORT BOOL CALLBACK AddStringA(PCSTR);
EXPORT BOOL CALLBACK AddStringW(PCWSTR);
EXPORT BOOL CALLBACK DeleteStringA(PCSTR);
EXPORT BOOL CALLBACK DeleteStringW(PCWSTR);
EXPORT int CALLBACK GetStringsA(GETSTRCB, PVOID);
EXPORT int CALLBACK GetStringsW(GETSTRCB, PVOID);
#ifdef UNICODE
#define AddString AddStringW
#define DeleteString DeleteStringW
#define GetStrings GetStringsW
#else
#define AddString AddStringA
#define DeleteString DeleteStringA
#define GetStrings GetStringsA
#endif
#include <windows.h>
#include "strlib.h"
#include "resource.h"
typedef struct
{
HDC hdc;
int xText;
int yText;
int xStart;
int yStart;
int xIncr;
int yIncr;
int xMax;
int yMax;
}
CBPARAM;
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
TCHAR szAppName[] = TEXT("StrProg");
TCHAR szString[MAX_LENGTH + 1];
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
HWND hwnd;
MSG msg;
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = szAppName;
wc.lpszClassName = szAppName;
if (!RegisterClass(&wc))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"),
szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, TEXT("DLL Demonstration Program"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
SendDlgItemMessage(hDlg, IDC_STRING, EM_LIMITTEXT, MAX_LENGTH, 0);
return TRUE;
case WM_COMMAND:
switch (wParam)
{
case IDOK:
GetDlgItemText(hDlg, IDC_STRING, szString, MAX_LENGTH);
EndDialog(hDlg, TRUE);
return TRUE;
case IDCANCEL:
EndDialog(hDlg, FALSE);
return TRUE;
}
}
return FALSE;
}
BOOL CALLBACK GetStrCallBack(PTSTR pString, CBPARAM* pcbp)
{
TextOut(pcbp->hdc, pcbp->xText, pcbp->yText,
pString, lstrlen(pString));
if ((pcbp->yText += pcbp->yIncr) > pcbp->yMax)
{
pcbp->yText = pcbp->yStart;
if ((pcbp->xText += pcbp->xIncr) > pcbp->xMax)
return FALSE;
}
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HINSTANCE hInst;
static int cxChar, cyChar, cxClient, cyClient;
static UINT iDataChangeMsg;
CBPARAM cbparam;
HDC hdc;
PAINTSTRUCT ps;
TEXTMETRIC tm;
switch (message)
{
case WM_CREATE:
hInst = ((LPCREATESTRUCT)lParam)->hInstance;
hdc = GetDC(hwnd);
GetTextMetrics(hdc, &tm);
cxChar = (int) tm.tmAveCharWidth;
cyChar = (int) (tm.tmHeight + tm.tmExternalLeading);
ReleaseDC(hwnd, hdc);
iDataChangeMsg = RegisterWindowMessage(TEXT("StrProgDataChange"));
return 0;
case WM_COMMAND:
switch (wParam)
{
case IDM_ENTER:
if (DialogBox(hInst, TEXT("EnterDlg"), hwnd, &DlgProc))
{
if (AddString(szString))
PostMessage(HWND_BROADCAST, iDataChangeMsg, 0, 0);
else
MessageBeep(0);
}
break;
case IDM_DELETE:
if (DialogBox(hInst, TEXT("DeleteDlg"), hwnd, &DlgProc))
{
if (DeleteString(szString))
PostMessage(HWND_BROADCAST, iDataChangeMsg, 0, 0);
else
MessageBeep(0);
}
break;
}
return 0;
case WM_SIZE:
cxClient = (int) LOWORD(lParam);
cyClient = (int) HIWORD(lParam);
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
cbparam.hdc = hdc;
cbparam.xText = cbparam.xStart = cxChar;
cbparam.yText = cbparam.yStart = cyChar;
cbparam.xIncr = cxChar * MAX_LENGTH;
cbparam.yIncr = cyChar;
cbparam.xMax = cbparam.xIncr * (1 + cxClient / cbparam.xIncr);
cbparam.yMax = cyChar * (cyClient / cyChar - 1);
GetStrings((GETSTRCB) GetStrCallBack, (PVOID) &cbparam);
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
if (message == iDataChangeMsg)
InvalidateRect(hwnd, NULL, TRUE);
break;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
The resource files, are in this case unnecessary.
I would appreciate any kind of help on this one.
Thank you.
|