windows核心编程第三章学习事件内核对象代码

    本文是看书时调试时的代码。主要用于调试事件内核对象的继承性。但是有一个问题始终无法解决,程序中父进程已经修改了事件内核对象的继承性为FALSE,但第二个子进程依然能够访问,要按值传递事件内核对象,需要在父子进程中传递内核对象时用注释的代码。都是win32工程。源码如下:

// HandInherit.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <Windows.h>
#include "../ComWnd/CommonWnd.h"

int _tmain(int argc, _TCHAR* argv[])
{
 printf( "父进程运行...\n");

 SECURITY_DESCRIPTOR sd;
 InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION);
 SetSecurityDescriptorDacl(&sd,TRUE,NULL,FALSE);

 SECURITY_ATTRIBUTES sa;
 sa.nLength = sizeof(sa);
 sa.bInheritHandle = TRUE; // 句柄可被子进程继承
 sa.lpSecurityDescriptor = &sd;

 TCHAR szEventName[] = "zsEvent";
 HANDLE hEvent = ::CreateEvent( &sa, TRUE, TRUE, szEventName );
 if( NULL == hEvent )
 {
  DWORD dwError = GetLastError();
  char cMsg[1024];
  BOOL bGet = GetLastErrorMsg( cMsg, dwError );
  printf("创建事件内核对象失败:%s\n", cMsg );
  system("PAUSE");
  return 0;
 }

 printf( "事件:0x%x\n", hEvent );

 STARTUPINFO si = { sizeof(si) };  
 PROCESS_INFORMATION pi; 
 
 TCHAR cmdLine[100] = {0};
  TCHAR szPath[MAX_PATH] = {0};
 ZeroMemory( szPath, MAX_PATH );
 int iLen = GetCurrentPath( szPath );

 TCHAR cAppName[MAX_PATH];
 ZeroMemory( cAppName, MAX_PATH );
 sprintf( cAppName, "%sChildProcess.exe", szPath );
 char cHandle[MAX_PATH] = {0};
// sprintf( cHandle, "%x", hEvent ); // 按值传递
 sprintf( cHandle, "%s", szEventName );
 sprintf( cmdLine, "%s %s", cAppName, cHandle );
 printf( "创建子进程1\n" );
 BOOL bOk = CreateProcess(
  cAppName,
  cmdLine,
  NULL,
  NULL,
  TRUE,
  CREATE_FORCEDOS | CREATE_NEW_CONSOLE,
  NULL,
  NULL,
  &si,
  &pi );

 if( !bOk )
 {
  DWORD dwError = GetLastError();
  char cMsg[1024];
  BOOL bGet = GetLastErrorMsg( cMsg, dwError );
  printf("创建子进程1失败:%s\n", cMsg );
  system("PAUSE");
  return 0;
 }
 
 HANDLE hChildPros = pi.hProcess;
 printf( "子进程1句柄值:%x\n", hChildPros );
 DWORD dwRt =  WaitForSingleObject( pi.hProcess, INFINITE ); // WaitForInputIdle
 if( dwRt == WAIT_OBJECT_0 )
 {
  printf( "成功等待子进程结束\n" );
 // printf( "成功等待子进程1初始化\n" );
 }
 else if( WAIT_FAILED == dwRt )
 {
  DWORD dwError = GetLastError();
  char cMsg[1024];
  BOOL bGet = GetLastErrorMsg( cMsg, dwError );
  printf( "等待子进程1结束失败:%s\n", cMsg );
 // printf( "等待子进程1初始化失败:%s\n", cMsg );
 }

 BOOL bInherit = TRUE;
 DWORD dwFlags;
 GetHandleInformation(hEvent, &dwFlags);
 bInherit = (0 != ( dwFlags & HANDLE_FLAG_INHERIT ) );
 
 BOOL bSet = SetHandleInformation( hEvent, HANDLE_FLAG_INHERIT, 0 ); // 设置为不可继承状态
 BOOL bSet2 = ResetEvent(hEvent);
 if( !bSet )
 {
  DWORD dwError = GetLastError();
  char cMsg[1024]={0};
  ZeroMemory( cMsg, 1024 );
  BOOL bGet = GetLastErrorMsg( cMsg, dwError );
  printf( "关闭事件对象(或者重置)继承性失败:%s\n", cMsg );
 }

 GetHandleInformation(hEvent, &dwFlags);
 bInherit = (0 != ( dwFlags & HANDLE_FLAG_INHERIT ) );

 Sleep(100);

 printf( "创建子进程2\n" );
 STARTUPINFO si2 = { sizeof(si2) };  
 PROCESS_INFORMATION pi2; 
 bOk = CreateProcess(
  cAppName,
  cmdLine,
  NULL,
  NULL,
  TRUE,
  CREATE_FORCEDOS | CREATE_NEW_CONSOLE,
  NULL,
  NULL,
  &si2,
  &pi2 );

 if( !bOk )
 {
  printf("创建子进程2失败%d\n",GetLastError() );
  system("PAUSE");
  return 0;
 }

 HANDLE hChildPros2 = pi2.hProcess;
 printf( "子进程2句柄值:%x\n", hChildPros2 );
 dwRt =  WaitForSingleObject( pi2.hProcess, INFINITE ); //WaitForInputIdle
 if( dwRt == WAIT_OBJECT_0 )
 {
  printf( "成功等待子进程2结束\n" );
 // printf( "成功等待子进程2初始化\n" );
 }
 else if( WAIT_FAILED == dwRt )
 {
  DWORD dwError = GetLastError();
  char cMsg[1024];
  BOOL bGet = GetLastErrorMsg( cMsg, dwError );
  printf( "等待子进程2结束失败:%s\n", cMsg );
 // printf( "等待子进程2初始化失败:%s\n", cMsg );
 }

 CloseHandle(hEvent);
 system("PAUSE");

 return 0;
}

// ChildProcess.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include "../ComWnd/CommonWnd.h"


int _tmain(int argc, _TCHAR* argv[])
{
 printf( "子进程运行...\n");
 if( argc < 2 )
 {
  printf( "没有传递命令行参数\n" );
  char* p = argv[0];
  printf( "%s\n", p );
  system( "PAUSE" );
  return 0;
 } 

 LPSTR lpCmdLine = GetCommandLine();
 printf( "命令行:%s\n", lpCmdLine ); 

 HANDLE hEvent = NULL;
 char cPath[MAX_PATH] = {0};
 char cHand[MAX_PATH] = {0};;
 sscanf( lpCmdLine, "%s %s", cPath, cHand );
// hEvent = (HANDLE)atoi( cHand ); // 按值传递
// hEvent = CreateEvent( NULL, TRUE, TRUE , cHand );
 hEvent = OpenEvent( EVENT_ALL_ACCESS, TRUE, cHand );
 printf( "事件解析为:%s\n", cHand );
 if( NULL == hEvent )
 {
  DWORD dwError = GetLastError();
  char cMsg[1024];
  BOOL bGet = GetLastErrorMsg( cMsg, dwError );
  printf( "打开事件内核对象失败:%s\n", cMsg );
  system("PAUSE");
  return 0;
 }

 DWORD dwRt = WaitForSingleObject( hEvent, INFINITE );
 if( dwRt == WAIT_TIMEOUT )
 {
  printf( "等待超时\n");
 }
 else if( WAIT_OBJECT_0 == dwRt )
 {
  printf( "成功等待父进程重置事件\n" );

  char szPath[MAX_PATH];
  ZeroMemory( szPath, MAX_PATH );
  int iLen = GetCurrentPath( szPath );
  strcpy( &szPath[iLen], _T("abc.txt") );

  HANDLE hFile = CreateFile(
   szPath,
   GENERIC_WRITE|GENERIC_READ,
   FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
   NULL,  
   CREATE_ALWAYS, // OPEN_EXISTING,
   FILE_ATTRIBUTE_NORMAL,
   NULL);

  if( INVALID_HANDLE_VALUE != hFile )
  {
   DWORD iSize = 0;
   char cTmp[100];
   sprintf( cTmp, "事件内核对象的名称是:%x", hEvent );
   BOOL bWrite = WriteFile(hFile, cTmp, strlen(cTmp), &iSize, NULL );
   if( !bWrite )
   {
    DWORD dwError = GetLastError();
    char cMsg[1024];
    BOOL bGet = GetLastErrorMsg( cMsg, dwError );
    printf( "创建文件成功,写文件失败:%s", cMsg );
   }
   else
   {
    printf( "创建文件成功,写入文件%d个字符\n", iSize);
   }
   CloseHandle(hFile);
  }
  else
  {
   DWORD dwError = GetLastError();
   char cMsg[1024];
   BOOL bGet = GetLastErrorMsg( cMsg, dwError );
   printf( "创建文件失败:%s\n", cMsg );
  }
 }
 else if( WAIT_ABANDONED == dwRt )
 {
  printf( "解析事件有误\n" );
 }
 else if( WAIT_FAILED == dwRt )
 {
  DWORD dwError = GetLastError();
  char cMsg[1024];
  BOOL bGet = GetLastErrorMsg( cMsg, dwError );
  printf( "等待事件失败:%s\n", cMsg );
 }

 printf( "等待事件内核对象返回%d\n", dwRt );

 CloseHandle(hEvent);
 system( "PAUSE" );

 return 0;
}

// CommonWnd.h 头文件
// 公共代码

#pragma once

#include <Windows.h>

BOOL GetLastErrorMsg( char* pBuf, DWORD dwError );

int GetCurrentPath( char* szPath );

// CommonWnd.cpp 文件

#include "StdAfx.h"
#include "CommonWnd.h"


int GetCurrentPath( char* szPath )
{
 TCHAR szLibFile[MAX_PATH];
 GetModuleFileName( NULL, szLibFile, MAX_PATH );

 TCHAR szTmp[MAX_PATH] = {0};
 strcpy( szTmp, szLibFile );

 char seps[]   = "\\";

 char* pTmpTok = NULL;
 char* token = strtok( szLibFile, seps );
 while( token != NULL )
 {
  pTmpTok = token;
  token = strtok( NULL, seps );
 }
 int iPathLen = pTmpTok - szLibFile;
 strncpy( szPath, szTmp, iPathLen );
 szPath[iPathLen] = 0;

 return iPathLen;
}

BOOL GetLastErrorMsg( char* pBuf, DWORD dwError )
{
 BOOL bGet = FALSE;
 HLOCAL hlocal = NULL;   // Buffer that gets the error message string

 // Use the default system locale since we look for Windows messages.
 // Note: this MAKELANGID combination has 0 as value
 DWORD systemLocale = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);

 // Get the error code's textual description
 BOOL fOk = FormatMessage(
  FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
  FORMAT_MESSAGE_ALLOCATE_BUFFER,
  NULL, dwError, systemLocale,
  (PTSTR) &hlocal, 0, NULL);

 if (!fOk)
 {
  // Is it a network-related error?
  HMODULE hDll = LoadLibraryEx(TEXT("netmsg.dll"), NULL,
   DONT_RESOLVE_DLL_REFERENCES);

  if (hDll != NULL)
  {
   fOk = FormatMessage(
    FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS |
    FORMAT_MESSAGE_ALLOCATE_BUFFER,
    hDll, dwError, systemLocale,
    (PTSTR) &hlocal, 0, NULL);
   FreeLibrary(hDll);
  }
 }

 if ( fOk && (hlocal != NULL) )
 { 
  strcpy( pBuf, (PCTSTR)LocalLock(hlocal) );
  LocalFree(hlocal);
  bGet = TRUE;
 }
 else
 { 
  strcpy( pBuf, "No text found for this error number" );
  bGet = TRUE;
 }

 return bGet;
}

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值