|
|
1.1 ! root 1: /*************************************************************************\ ! 2: * PROGRAM: Mutex.c ! 3: * ! 4: * PURPOSE: ! 5: * ! 6: * To demonstrate the use of a named mutex between processes. ! 7: * ! 8: * GLOBAL VARIABLES: ! 9: * ! 10: * HANDLE hInst; - Instance handle. ! 11: * ! 12: * HWND hWnd; - Client window handle. ! 13: * ! 14: * CHAR Buf[80], Buf2[80]; ! 15: * Error message buffers. ! 16: * ! 17: * FUNCTIONS: ! 18: * ! 19: * WinMain() - Initializes the window, and process the message loop. ! 20: * MainWndProc() - To handle the messages to the main window. ! 21: * RequestProc() - Prints a message when it gets access to the mutex. ! 22: * ! 23: * COMMENTS: ! 24: * ! 25: * Overview: ! 26: * Between processes it is better to use a mutex than a semaphore ! 27: * to control access to a mutual resourse. A serious draw back ! 28: * to a semaphore is that any thread can call ReleaseSemaphore ! 29: * and change its usage count (or access). Another drawback is that ! 30: * if a thread or process dies before calling ReleaseSemaphore, than ! 31: * no other process or thread will be able to access it (because the ! 32: * use count hasn't been updated). When a process controlling ! 33: * a mutex dies, the mutex is freed for other processes. ! 34: * ! 35: * To Use: ! 36: * Start any number of instances of this application. Each instance ! 37: * will start a thread which will request access to the mutex. ! 38: * when the thread has the mutex, it will print a message in the ! 39: * application window "I HAVE CONTROL OF THE MUTEX!", and then ! 40: * sleep for two seconds. It will then wakeup, erase the message, ! 41: * release the mutex; and then sleep for another two seconds before ! 42: * asking for control again. By starting several instances, you will ! 43: * see that each instance will often have to wait longer than its two ! 44: * seconds before it gets control. ! 45: * ! 46: \*************************************************************************/ ! 47: ! 48: #include <windows.h> ! 49: #include <stdlib.h> ! 50: #include <stdio.h> ! 51: #include "mutex.h" ! 52: ! 53: // used for error messages. ! 54: #define WERR(who,where) {sprintf(Buf,"ERROR: %s returned %u, line: %u", who, GetLastError(), __LINE__);\ ! 55: sprintf(Buf2,"From within %s", where);\ ! 56: MessageBox(hWnd, Buf, Buf2, MB_OK);} ! 57: ! 58: ! 59: CHAR Buf[80]; ! 60: CHAR Buf2[80]; ! 61: HANDLE hInst; ! 62: HWND hWnd; ! 63: ! 64: ! 65: ! 66: ! 67: /*************************************************************************\ ! 68: * ! 69: * FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int) ! 70: * ! 71: * PURPOSE: Calls initialization function, processes message loop. ! 72: * ! 73: * COMMENTS: A fairly standard WinMain. ! 74: * ! 75: \*************************************************************************/ ! 76: ! 77: int APIENTRY WinMain (HANDLE hInstance, ! 78: HANDLE hPrevInstance, ! 79: LPSTR lpCmdLine, ! 80: int nCmdShow) ! 81: ! 82: ! 83: { ! 84: ! 85: MSG msg; ! 86: WNDCLASS wc; ! 87: ! 88: UNREFERENCED_PARAMETER( lpCmdLine ); ! 89: UNREFERENCED_PARAMETER( hPrevInstance ); ! 90: ! 91: hInst = hInstance; ! 92: ! 93: wc.style = NULL; // Replaces CS_SIZEREDRAW. ! 94: wc.lpfnWndProc = (WNDPROC)MainWndProc; // The client window procedure. ! 95: wc.cbClsExtra = 0; // No room reserved for extra data. ! 96: wc.cbWndExtra = 0; ! 97: wc.hInstance = hInstance; ! 98: wc.hIcon = LoadIcon (NULL, IDI_APPLICATION); ! 99: wc.hCursor = LoadCursor (NULL, IDC_ARROW); ! 100: wc.hbrBackground = GetStockObject (WHITE_BRUSH); ! 101: wc.lpszMenuName = ""; ! 102: wc.lpszClassName = "MutexWClass"; ! 103: ! 104: RegisterClass(&wc); ! 105: ! 106: hWnd = CreateWindow ("MutexWClass", ! 107: "Mutex Between Processes Sample", ! 108: WS_OVERLAPPEDWINDOW, ! 109: CW_USEDEFAULT, ! 110: CW_USEDEFAULT, ! 111: CW_USEDEFAULT, ! 112: CW_USEDEFAULT, ! 113: NULL, ! 114: NULL, ! 115: hInstance, ! 116: NULL); ! 117: ! 118: ! 119: ShowWindow (hWnd, nCmdShow); ! 120: ! 121: while (GetMessage (&msg, NULL, NULL, NULL)) ! 122: DispatchMessage (&msg); // Dispatch message to window. ! 123: ! 124: return (msg.wParam); // Returns value from PostQuitMessage. ! 125: ! 126: } ! 127: ! 128: /*************************************************************************\ ! 129: * ! 130: * FUNCTION: MainWndProc (HWND, UINT, UINT, LONG) ! 131: * ! 132: * PURPOSE: To process messages. To launch client and server threads ! 133: * as appropriate. ! 134: * ! 135: * ! 136: * MESSAGES: ! 137: * ! 138: * WM_CREATE - Creates a thread. ! 139: * ! 140: * WM_DESTROY - Standard, destroys the window. ! 141: * ! 142: * CALLED BY: ! 143: * ! 144: * WinMain(); ! 145: * ! 146: * CALLS TO: ! 147: * ! 148: * RequestProc() - The thread procedure. ! 149: * ! 150: \*************************************************************************/ ! 151: ! 152: LONG APIENTRY MainWndProc (HWND hwnd, ! 153: UINT message, ! 154: UINT wParam, ! 155: LONG lParam) ! 156: { ! 157: DWORD ThreadID; ! 158: HANDLE hThread; ! 159: ! 160: switch (message) ! 161: { ! 162: ! 163: case WM_CREATE: ! 164: ! 165: hThread = CreateThread (NULL, 0, ! 166: (LPTHREAD_START_ROUTINE)RequestProc, ! 167: (LPVOID)NULL, NULL, ! 168: (LPDWORD)&ThreadID); ! 169: if (!hThread) ! 170: WERR("CreateThread", "WM_CREATE"); ! 171: CloseHandle (hThread); ! 172: return (0); ! 173: ! 174: ! 175: case WM_DESTROY : ! 176: PostQuitMessage (0); ! 177: return (0); ! 178: } ! 179: return DefWindowProc (hwnd, message, wParam, lParam); ! 180: } ! 181: ! 182: ! 183: /*************************************************************************\ ! 184: * ! 185: * FUNCTION: VOID RequestProc (VOID) ! 186: * ! 187: * PURPOSE: This thread tries to create the Mutex. Only the first thread ! 188: * created will succeed, all others will fail. Then this thread ! 189: * tries to open the mutex. If successful, it ! 190: * enters a loop. The loop asks for control of the mutex. ! 191: * Once it has control, it prints the message in the application ! 192: * window, and sleeps for two seconds. It then releases ! 193: * the mutex, erases the message, and sleeps another two ! 194: * seconds before trying to get control again. ! 195: * ! 196: * VARIABLES USED: ! 197: * ! 198: * - hMutex: ! 199: * A handle to the mutex. ! 200: * ! 201: * - rect, textRect: ! 202: * RECT structures. One for the client area, one for the ! 203: * text location. ! 204: * ! 205: * - hDC: The DC of the window. ! 206: * ! 207: * - X, Y: Integers/coordinates used to locate the text ! 208: * ! 209: * - hBrush: ! 210: * Handle to a brush, used to erase the old text. ! 211: * ! 212: * - size: A SIZE struct, used to determin the size of the font ! 213: * and message on the window. ! 214: * ! 215: * ! 216: \*************************************************************************/ ! 217: VOID RequestProc(VOID) ! 218: { ! 219: HANDLE hMutex; ! 220: RECT rect, textRect; ! 221: HDC hDC; ! 222: LONG X, Y; ! 223: SIZE size; ! 224: DWORD retCode; ! 225: ! 226: ! 227: ! 228: hMutex = CreateMutex (NULL, FALSE, "my_mutex"); ! 229: if (!hMutex) ! 230: { ! 231: retCode = GetLastError(); ! 232: if (retCode != ERROR_ALREADY_EXISTS) ! 233: { ! 234: SetLastError(retCode); ! 235: WERR("CreateMutex", "WM_CREATE"); ! 236: PostQuitMessage(0); ! 237: } ! 238: } ! 239: ! 240: hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "my_mutex"); ! 241: if (!hMutex) ! 242: { ! 243: WERR("OpenMutex", "From RequestProc"); ! 244: return; ! 245: } ! 246: ! 247: hDC = GetDC (hWnd); ! 248: GetTextExtentPoint (hDC, "I HAVE CONTROL OF THE MUTEX!", 28, &size); ! 249: ReleaseDC (hWnd, hDC); ! 250: ! 251: while(!IsWindow(hWnd)); ! 252: ! 253: while(1) ! 254: { ! 255: WaitForSingleObject (hMutex, INFINITE); ! 256: ! 257: hDC = GetDC (hWnd); ! 258: GetClientRect (hWnd, &rect); ! 259: X = ((rect.right - rect.left) / 2) - (size.cx / 2); ! 260: Y = (rect.bottom - rect.top) / 2; ! 261: ! 262: TextOut (hDC, X, Y, "I HAVE CONTROL OF THE MUTEX!", 28); ! 263: ! 264: MessageBeep (0); // Forces a flush of the window buffers. ! 265: Sleep(2000); ! 266: ! 267: textRect.left = X, ! 268: textRect.right = X + size.cx; ! 269: textRect.top = Y; ! 270: textRect.bottom = Y + size.cy; ! 271: FillRect (hDC, &textRect, GetStockObject(WHITE_BRUSH)); ! 272: ! 273: ReleaseDC(hWnd, hDC); ! 274: ReleaseMutex (hMutex); ! 275: Sleep(2000); ! 276: } ! 277: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.