RIFF AudioEncoding Values

Programming/C,CPP,CS 2021. 4. 22. 15:50 Posted by TanSanC
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

These "TwoCC" audio encoding codes are used in RIFF and ASF files.

 

 

 

 

www.bibliotecacpa.org.ar/greenstone/perllib/cpan/Image/ExifTool/RIFF.pm

 

C# String.format 사용법

Programming/C,CPP,CS 2021. 3. 17. 14:15 Posted by TanSanC
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

String Format for Int [C#]

Integer numbers can be formatted in .NET in many ways. You can use static method String.Format or instance method int.ToString. Following examples show how to align numbers (with spaces or zeroes), how to format negative numbers or how to do custom formatting like phone numbers.

Add zeroes before number

To add zeroes before a number, use colon separator „:“ and write as many zeroes as you want.

[C#]
String.Format("{0:00000}", 15); // "00015" String.Format("{0:00000}", -15); // "-00015"

Align number to the right or left

To align number to the right, use comma „,“ followed by a number of characters. This alignment option must be before the colon separator.

[C#]
String.Format("{0,5}", 15); // " 15" String.Format("{0,-5}", 15); // "15 " String.Format("{0,5:000}", 15); // " 015" String.Format("{0,-5:000}", 15); // "015 "

Different formatting for negative numbers and zero

You can have special format for negative numbers and zero. Use semicolon separator „;“ to separate formatting to two or three sections. The second section is format for negative numbers, the third section is for zero.

[C#]
String.Format("{0:#;minus #}", 15); // "15" String.Format("{0:#;minus #}", -15); // "minus 15" String.Format("{0:#;minus #;zero}", 0); // "zero"

Custom number formatting (e.g. phone number)

Numbers can be formatted also to any custom format, e.g. like phone numbers or serial numbers.

[C#]
String.Format("{0:+### ### ### ###}", 447900123456); // "+447 900 123 456" String.Format("{0:##-####-####}", 8958712551); // "89-5871-2551"

 

 

출처 : www.csharp-examples.net/string-format-int/

 

String Format for Int [C#]

String Format for Int [C#] Integer numbers can be formatted in .NET in many ways. You can use static method String.Format or instance method int.ToString. Following examples show how to align numbers (with spaces or zeroes), how to format negative numbers

www.csharp-examples.net

 

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

 

 

 

ConfigurationSettings.AppSettings

 

->

 

System.Configuration.ConfigurationManager.AppSettings

RegisterClientScriptBlock

Programming/C,CPP,CS 2020. 7. 21. 16:52 Posted by TanSanC
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

RegisterClientScriptBlock

 

Page.RegisterClientScriptBlock( A, B );

 

->

 

 

Page.ClientScript.RegisterClientScriptBlock( this.GetType(), A, B );

 

 

 

 

 

 

 

 

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

[C#] 형식 또는 네임스페이스 이름을 찾을 수 없습니다. using 지시문 또는 어셈블리 참조가 있는지 확인하세요.

 

특정 using 문의 참조를 사용 할 수 없다는 에러이다.

 

 

using 에 사용되는

 

1) 라이브러리가 없거나

 

2) 빌드 순서로 인해 아직 빌드되지 않았거나

 

3) 대상 프레임워크가 달라서 제대로 참조가되지 않거나

 

 

 

 

 

'Programming > C,CPP,CS' 카테고리의 다른 글

[C#] ConfigurationSettings.AppSettings 경고  (0) 2020.07.21
RegisterClientScriptBlock  (0) 2020.07.21
[NTP] CNtpTime, sntp.h, sntp.cpp 의 문제점 정리  (0) 2019.12.24
[CPP] NTP Sync LocalClockOffset  (0) 2019.12.23
ActiveX 웹배포  (0) 2019.12.10
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

[NTP] CNtpTime, sntp.h, sntp.cpp 의 문제점 정리

 

NTP 프로토콜을 이용하여 클라이언트 시간 동기화시

 

sntp.h, sntp.cpp 로 만들어진

 

CNtpTime 클래스를 많이 사용하는것 같다.

 

ex)

 

https://github.com/hsluoyz/rmtsvc/blob/master/net4cpp21/protocol/sntpclnt.cpp

 

hsluoyz/rmtsvc

A web-based remote desktop & control service for Windows. - hsluoyz/rmtsvc

github.com

http://read.pudn.com/downloads142/sourcecode/hack/trojan/616424/sntpclient%202008-08-03/NtpTime.c__.htm

 

sntpclient.rar NtpTime.c

www.pudn.com > sntpclient.rar > NtpTime.c, change:2008-08-25,size:4890b #include "NtpTime.h" #include "datatype.h" #include #include #define FALSE 0 SYSTEMTIME st; CNtpTimePacket host2network(CNtpTimePacket ntp) //transform the host byte order to network b

read.pudn.com

https://github.com/domz1/integrity/blob/master/Source/Virtuos_v17/Build/Program/_Network/Misc/Src/Sntp.cpp

 

domz1/integrity

Contribute to domz1/integrity development by creating an account on GitHub.

github.com

 

위 코드들 모두 누군가 만든 CNtpTime 을 그대로 사용하고있는데...

 

그런데 이 클래스에 문제점이 있다.

 

 

 

CNtpTime::operator SYSTEMTIME() 

 

CNtpTime 을 SystemTime 으로 형변환 해주는 오퍼레이터 함수인데

 

 

  st.wMilliseconds = NtpFractionToMs(Fraction());

 

이 부분에 문제가 있다.

 

Fraction 을 Milliseconds 로 변경한 결과가 1000 이 되는 경우가 발생한다.

 

NtpTime 실제 값을 저장 할 시에

 

FileTime 을 사용하는데

 

FileTime 은

 

Second 와 NanoSecond 를 구분하여 16진수 기준 앞 8자리 뒤 8자리로 표현한다.

 

NanoSecond 의 값이 0x100000000 이 1Second 인데

 

NanoSecond 의 표현부는 0xFFFFFFF 이므로 1Second 도 0xFFFFFFF 로 표기된다.

 

 

 

CNtpTime::operator SYSTEMTIME() const
{
// Currently this function only operates correctly in
// the 1900- 2036 primary epoch defined by NTP
SYSTEMTIME st;
DWORD s = Seconds();
st.wSecond = (WORD)( s % 60 );
s /= 60;
st.wMinute = (WORD)( s % 60 );
s /= 60;
st.wHour = (WORD)( s % 24 );
s /= 24;
long JD = s + JAN_1ST_1900;
st.wDayOfWeek = (WORD)( ( JD + 1 ) % 7 );
GetGregorianDate( JD, st.wYear, st.wMonth, st.wDay );
st.wMilliseconds = NtpFractionToMs( Fraction() );
 
return st;
}

 

위 구조 상

 

NtpFractionToMs( Fraction() ) 의 결과값이 1000 이어도

 

Second 로의 올림이 발생하지 않아서

 

Milliseconds 가 1000 인 채로 다음 연산으로 넘어가게 된다.

 

 

Milliseconds 가 1000 인 상태에서

 

SystemTime 을 FileTime 으로 바꾸는 SystemTimeToFileTime 함수를 실행하게 되면

 

비정상값이 리턴된다.

 

 

 

 

 

[CPP] NTP Sync LocalClockOffset

Programming/C,CPP,CS 2019. 12. 23. 23:52 Posted by TanSanC
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

[CPP] NTP Sync LocalClockOffset

 

NTP 는

 

Network Time Protocol 으로 네트워크를 통해 시간을 동기화 하는 프로토콜입니다.

 

NTP 서버 시간에 클라이언트 시간을 맞추기 위한 프로토콜입니다.

 

 

 

[현재 시점] 서버의 현재 시간과 클라이언트의 현재 시간이 다를 수 있고,

 

[지속 되는 상태] 서버의 1초와 클라이언트의 1초가 다를 수 있습니다.

 

 

 

서버 혹은 클라이언트간 시간이 아주 중요한 프로그램에서는

 

NTP 는 한번만 수행하는 것이 아닌 지속적으로 수행하여 동기화 하게 됩니다.

 

 

 

 

 

서버와 클라이언트의 시간 차이를 LocalClockOffset 으로 표기합니다.

 

 

 

 

여러 클라이언트의 시간을

 

NTP서버와 동기화하여

 

각 클라이언트간 시간이 동기화 하도록 하기 위해 사용 되는 값이 offset 입니다.

 

 

 

계산 식은

Timestamp Name ID When Generated

------------------------------------------------------------

Originate Timestamp T1 time request sent by client      C1

Receive Timestamp T2 time request received by server  S1

Transmit Timestamp T3 time reply sent by server         S2

Destination Timestamp T4 time reply received by client C2

 

The roundtrip delay d and system clock offset t are defined as:

 

d = (T4 - T1) - (T3 - T2)

t = ((T2 - T1) + (T3 - T4)) / 2.

t = ((S1 - C1) + (S2 - C2)) / 2.

 

여기서

 

 

 

 

여기서 서버와 클라리언트가 패킷을 주고 받는데 걸리는 딜레이(delay1, delay2)는 같다고 가정한다.

 

 

 

 

ActiveX 웹배포

Programming/C,CPP,CS 2019. 12. 10. 11:49 Posted by TanSanC
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

***** 1.인증하기-퍼온 글입니다 *****

 

 ▶ Step1. 파일명.CAB 을 인증서가 있는 폴더에 붙여넣습니다.

 

 

▶ Step 2. MSDOS 프롬프트에서 ActiveX Control이 모여있는 폴더로 이동한 뒤 다음과 같이  입력합니다.

    makecert -n "CN=test" -sv test.pvk test.cer  

 

 

▶ Step 3. 다음과 같이 개인공개키를 생성하는 화면이 나타납니다.

    적당한 패스워드를 입력해 주십시오.     

 

▶ Step 4. test.pvk와 test.cer 파일이 생성됩니다. 생성된 ser 파일을 이용해서 spc 파일을  생성합니다. dos 창에서 아래와같이 입력합니다.

    cert2spc test.cer test.spc  

 

▶ Step 5. Succeeded라는 메시지가 나타나고 spc 파일이 성공적으로 생성된것입니다.

    cab 파일 서명을 위해 다음과 같이 입력합니다.  

    signcode -spc test.spc -v test.pvk -n "test" 파일명.cab

 

▶ Step 6. 이전에 설정한 비밀번호를 입력합니다.  

 

▶ Step 7. Test Sign 과정이 마무리됩니다. DOS 창에서 다음과 같이 인증확인을 해볼 수 있습니다.

   chktrust 파일명.cab  

 

  * 생성과정 중간에 Warning은 서명한 시간이 없어서 그런 것인데,

   테스트용은 원래 시간을 적지 않습니다.

 

▶ Step 8. 인증한 파일명.CAB파일(인증하기명령어가 있는 폴더에 붙여넣은 파일)을 원하는 폴더(웹호스팅폴더)에 업로드합니다.

 

 

 

 

***** 2.배포하기 *****

<!--

이부분은 보통 필요하지 않으므로 주석상태 이대로 두시면 됩니다.

<OBJECT CLASSID="clsid:5220cb21-c88d-11cf-b347-00aa00a28331">

    <PARAM NAME="LPKPath" VALUE="LPKfilename.LPK">

</OBJECT>

-->

 

<OBJECT ID="test1"

CLASSID="clsid:D743E11F-1E3D-4290-8844-D8DB1A36A5B7" CODEBASE="download/ocx/test1.CAB#version=1,0,4,0">

</OBJECT>

 

▶ clsid:D743E11F-1E3D-4290-8844-D8DB1A36A5B7 이부분은 CAB만드시고 압축을 풀어보시면

   test1.inf파일을 열어서 보시면 [test1.ocx]부분에 보시면 clsid={D743E11F-1E3D-4290-8844-D8DB1A36A5B7} 이걸 적어주시면 됩니다.

 

▶ CODEBASE는 위에 분의 말씀대로 다운로드 받을 경로(상대 or절대경로)적어주시고 #Version은 수정될때 업데이트 할때 필요합니다.

 

 

 

 

***** 3.체크하기 ***** 

 

만약 [1.인증하기]에서 chktrust 파일명.cab 했을때 설치할건지 물어보는 창이 뜬는데...

설치가 안된다.

 

[익스플로어]-[도구]-[인터넷옵션]-[보안]-[사용자지정수준]-[ActiveX컨트롤 및 플러그인]

 

  1.서명 안 된 ActiveX컨트롤 다운로드 - [사용] or [확인] 에 체크하십시오.

  2.안전하지 않은 것으로 표시된 ActiveX컨트롤 초기화 및 스크립팅 - [사용] or [확인] 에 체크

     -이 부분에 [사용안함]으로 체크시 웹코딩에서 <PARAM>으로 ActiveX에 프로퍼티넘길때 작동하지 않고

      스크립팅에서도 작동하지 않음

  3.ActiveX컨트롤 및 플로그인 실행  - [사용]체크해야 되겠죠

 

 

 

**** 배포전에 수동설치로 테스트하기 *****

 

우선 배포전에 해당ActiveX를 수동으로 로컬PC에 설치해보십시오.

1. WINDOW\system32\폴더에 해당OCX파일을 복사하시고

2. [실행]-regsvr32 파일명.ocx 로 레지스트리에 등록

3. 웹코딩에서 해당 ocx의 CLASSID="CLSID:D743E11F-1E3D-4290-8844-D8DB1A36A5B7"로 참조

4. 웹페이제에서 작동하면 OCX에는 이상이 없는 거겠죠

5. 설치한 OCX제거하기

6. [실행]-[regedit]-[HKEY_CLASSES_ROOT]-[편집메뉴]-[찾기]-D743E11F-1E3D-4290-8844-D8DB1A36A5B7복사

7. {D743E11F-1E3D-4290-8844-D8DB1A36A5B7}에 커서가 선택되어 있으면 [마우스오른쪽버튼]-[삭제]

8. 열어둔 익스플로어 닫고 새로 열어서 테스트 화면을 엽니다.(새로고침하면 계속작동이 됩니다.)

9. 그러면 해당OCX가 삭제 되서 OCX가 작동하지 않겠죠

10. 배포방법이 올바르면 설치할건지 알림창이 하나 뜨겠죠.

11. 설치 눌러서 설치가 됐다면 OCX가 제대로 작동하겠죠.

12. 만약에 설치창이 뜨고 [예]를 눌러서 설치를 했는데도 작동을 하지 않는다면...

13. 6번 방법으로 해당 OCX가 설치되었는지 확인하십시오.

14. 설치가 됐는데도 안 뜬다면...  [3.체크하기]의 보안-ActiveX의 사용여부 사항을 체크을 확인하시기 바랍니다.

 

 

'Programming > C,CPP,CS' 카테고리의 다른 글

[NTP] CNtpTime, sntp.h, sntp.cpp 의 문제점 정리  (0) 2019.12.24
[CPP] NTP Sync LocalClockOffset  (0) 2019.12.23
ffmpeg sample  (0) 2018.06.20
중복 실행 방지 코드 (Mutex)  (0) 2018.04.18
WAVE form wFormatTag IDs  (0) 2018.04.04

ffmpeg sample

Programming/C,CPP,CS 2018. 6. 20. 09:46 Posted by TanSanC
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.


player.cpp(57): error C4996: 'av_register_all': deprecated로 선언되었습니다.


include\libavformat\avformat.h(2025) : 'av_register_all' 선언을 참조하십시오.


 

#include <libavcodec/avcodec.h>

#include <libavformat/avformat.h>

#include <libswscale/swscale.h>

 

#include <stdio.h>

 

// compatibility with newer API

#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,28,1)

#define av_frame_alloc avcodec_alloc_frame

#define av_frame_free avcodec_free_frame

#endif

 

void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame) {

      FILE *pFile;

      char szFilename[32];

      int  y;

 

      // Open file

      sprintf_s(szFilename, "frame%d.ppm", iFrame);

      fopen_s(&pFile, szFilename, "wb");

      if (pFile == NULL)

            return;

 

      // Write header

      fprintf(pFile, "P6\n%d %d\n255\n", width, height);

 

      // Write pixel data

      for (y = 0; y<height; y++)

            fwrite(pFrame->data[0] + y*pFrame->linesize[0], 1, width * 3, pFile);

 

      // Close file

      fclose(pFile);

}

 

 

int main(int argc, char *argv[]) {

      // Initalizing these to NULL prevents segfaults!

      AVFormatContext   *pFormatCtx = NULL;

      int               i, videoStream;

      AVCodecContext    *pCodecCtxOrig = NULL;

      AVCodecContext    *pCodecCtx = NULL;

      AVCodec           *pCodec = NULL;

      AVFrame           *pFrame = NULL;

      AVFrame           *pFrameRGB = NULL;

      AVPacket          packet;

      int               frameFinished;

      int               numBytes;

      uint8_t           *buffer = NULL;

      struct SwsContext *sws_ctx = NULL;

 

      if (argc < 2) {

            printf("Please provide a movie file\n");

            return -1;

      }

      // Register all formats and codecs

      av_register_all();

 

      // Open video file

      if (avformat_open_input(&pFormatCtx, argv[1], NULL, NULL) != 0)

            return -1; // Couldn't open file

 

      // Retrieve stream information

      if (avformat_find_stream_info(pFormatCtx, NULL)<0)

            return -1; // Couldn't find stream information

 

      // Dump information about file onto standard error

      av_dump_format(pFormatCtx, 0, argv[1], 0);

 

      // Find the first video stream

      videoStream = -1;

      for (i = 0; i<pFormatCtx->nb_streams; i++)

            if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {

                  videoStream = i;

                  break;

            }

      if (videoStream == -1)

            return -1; // Didn't find a video stream

 

      // Get a pointer to the codec context for the video stream

      pCodecCtxOrig = pFormatCtx->streams[videoStream]->codec;

      // Find the decoder for the video stream

      pCodec = avcodec_find_decoder(pCodecCtxOrig->codec_id);

      if (pCodec == NULL) {

            fprintf(stderr, "Unsupported codec!\n");

            return -1; // Codec not found

      }

      // Copy context

      pCodecCtx = avcodec_alloc_context3(pCodec);

      if (avcodec_copy_context(pCodecCtx, pCodecCtxOrig) != 0) {

            fprintf(stderr, "Couldn't copy codec context");

            return -1; // Error copying codec context

      }

 

      // Open codec

      if (avcodec_open2(pCodecCtx, pCodec, NULL)<0)

            return -1; // Could not open codec

 

      // Allocate video frame

      pFrame = av_frame_alloc();

 

      // Allocate an AVFrame structure

      pFrameRGB = av_frame_alloc();

      if (pFrameRGB == NULL)

            return -1;

 

      // Determine required buffer size and allocate buffer

      numBytes = avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,

            pCodecCtx->height);

      buffer = (uint8_t *)av_malloc(numBytes*sizeof(uint8_t));

 

      // Assign appropriate parts of buffer to image planes in pFrameRGB

      // Note that pFrameRGB is an AVFrame, but AVFrame is a superset

      // of AVPicture

      avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,

            pCodecCtx->width, pCodecCtx->height);

 

      // initialize SWS context for software scaling

      sws_ctx = sws_getContext(pCodecCtx->width,

            pCodecCtx->height,

            pCodecCtx->pix_fmt,

            pCodecCtx->width,

            pCodecCtx->height,

            PIX_FMT_RGB24,

            SWS_BILINEAR,

            NULL,

            NULL,

            NULL

            );

 

      // Read frames and save first five frames to disk

      i = 0;

      while (av_read_frame(pFormatCtx, &packet) >= 0) {

            // Is this a packet from the video stream?

            if (packet.stream_index == videoStream) {

                  // Decode video frame

                 avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);

 

                  // Did we get a video frame?

                  if (frameFinished) {

                        // Convert the image from its native format to RGB

                        sws_scale(sws_ctx, (uint8_t const * const *)pFrame->data,

                             pFrame->linesize, 0, pCodecCtx->height,

                             pFrameRGB->data, pFrameRGB->linesize);

 

                        // Save the frame to disk

                        if (++i <= 5)

                             SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height,

                             i);

                  }

            }

 

            // Free the packet that was allocated by av_read_frame

            av_free_packet(&packet);

      }

 

      // Free the RGB image

      av_free(buffer);

      av_frame_free(&pFrameRGB);

 

      // Free the YUV frame

      av_frame_free(&pFrame);

 

      // Close the codecs

      avcodec_close(pCodecCtx);

      avcodec_close(pCodecCtxOrig);

 

      // Close the video file

      avformat_close_input(&pFormatCtx);

 

      return 0;

}





Solution


https://github.com/intel/libyami-utils/commit/124712bfd4cccd43ab60bd160b0f8990d20e5911




'Programming > C,CPP,CS' 카테고리의 다른 글

[CPP] NTP Sync LocalClockOffset  (0) 2019.12.23
ActiveX 웹배포  (0) 2019.12.10
중복 실행 방지 코드 (Mutex)  (0) 2018.04.18
WAVE form wFormatTag IDs  (0) 2018.04.04
CString Tokenize  (0) 2017.10.19

중복 실행 방지 코드 (Mutex)

Programming/C,CPP,CS 2018. 4. 18. 15:08 Posted by TanSanC
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

중복 실행 방지 코드 (Mutex)


CreateMutex function


Creates or opens a named or unnamed mutex object.

To specify an access mask for the object, use the CreateMutexEx function.

Syntax

HANDLE WINAPI CreateMutex(
  _In_opt_ LPSECURITY_ATTRIBUTES lpMutexAttributes,
  _In_     BOOL                  bInitialOwner,
  _In_opt_ LPCTSTR               lpName
);

Parameters

lpMutexAttributes [in, optional]

A pointer to a SECURITY_ATTRIBUTES structure. If this parameter is NULL, the handle cannot be inherited by child processes.

The lpSecurityDescriptor member of the structure specifies a security descriptor for the new mutex. If lpMutexAttributes is NULL, the mutex gets a default security descriptor. The ACLs in the default security descriptor for a mutex come from the primary or impersonation token of the creator. For more information, see Synchronization Object Security and Access Rights.

bInitialOwner [in]

If this value is TRUE and the caller created the mutex, the calling thread obtains initial ownership of the mutex object. Otherwise, the calling thread does not obtain ownership of the mutex. To determine if the caller created the mutex, see the Return Values section.

lpName [in, optional]

The name of the mutex object. The name is limited to MAX_PATH characters. Name comparison is case sensitive.

If lpName matches the name of an existing named mutex object, this function requests the MUTEX_ALL_ACCESSaccess right. In this case, the bInitialOwner parameter is ignored because it has already been set by the creating process. If the lpMutexAttributes parameter is not NULL, it determines whether the handle can be inherited, but its security-descriptor member is ignored.

If lpName is NULL, the mutex object is created without a name.

If lpName matches the name of an existing event, semaphore, waitable timer, job, or file-mapping object, the function fails and the GetLastError function returns ERROR_INVALID_HANDLE. This occurs because these objects share the same namespace.

The name can have a "Global\" or "Local\" prefix to explicitly create the object in the global or session namespace. The remainder of the name can contain any character except the backslash character (\). For more information, see Kernel Object Namespaces. Fast user switching is implemented using Terminal Services sessions. Kernel object names must follow the guidelines outlined for Terminal Services so that applications can support multiple users.

The object can be created in a private namespace. For more information, see Object Namespaces.




#include <windows.h>
#include <stdio.h>

#define THREADCOUNT 2

HANDLE ghMutex; 

DWORD WINAPI WriteToDatabase( LPVOID );

int main( void )
{
    HANDLE aThread[THREADCOUNT];
    DWORD ThreadID;
    int i;

    // Create a mutex with no initial owner

    ghMutex = CreateMutex( 
        NULL,              // default security attributes
        FALSE,             // initially not owned
        NULL);             // unnamed mutex

    if (ghMutex == NULL) 
    {
        printf("CreateMutex error: %d\n", GetLastError());
        return 1;
    }

    // Create worker threads

    for( i=0; i < THREADCOUNT; i++ )
    {
        aThread[i] = CreateThread( 
                     NULL,       // default security attributes
                     0,          // default stack size
                     (LPTHREAD_START_ROUTINE) WriteToDatabase, 
                     NULL,       // no thread function arguments
                     0,          // default creation flags
                     &ThreadID); // receive thread identifier

        if( aThread[i] == NULL )
        {
            printf("CreateThread error: %d\n", GetLastError());
            return 1;
        }
    }

    // Wait for all threads to terminate

    WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE);

    // Close thread and mutex handles

    for( i=0; i < THREADCOUNT; i++ )
        CloseHandle(aThread[i]);

    CloseHandle(ghMutex);

    return 0;
}

DWORD WINAPI WriteToDatabase( LPVOID lpParam )
{ 
    // lpParam not used in this example
    UNREFERENCED_PARAMETER(lpParam);

    DWORD dwCount=0, dwWaitResult; 

    // Request ownership of mutex.

    while( dwCount < 20 )
    { 
        dwWaitResult = WaitForSingleObject( 
            ghMutex,    // handle to mutex
            INFINITE);  // no time-out interval
 
        switch (dwWaitResult) 
        {
            // The thread got ownership of the mutex
            case WAIT_OBJECT_0: 
                __try { 
                    // TODO: Write to the database
                    printf("Thread %d writing to database...\n", 
                            GetCurrentThreadId());
                    dwCount++;
                } 

                __finally { 
                    // Release ownership of the mutex object
                    if (! ReleaseMutex(ghMutex)) 
                    { 
                        // Handle error.
                    } 
                } 
                break; 

            // The thread got ownership of an abandoned mutex
            // The database is in an indeterminate state
            case WAIT_ABANDONED: 
                return FALSE; 
        }
    }
    return TRUE; 
}



'Programming > C,CPP,CS' 카테고리의 다른 글

ActiveX 웹배포  (0) 2019.12.10
ffmpeg sample  (0) 2018.06.20
WAVE form wFormatTag IDs  (0) 2018.04.04
CString Tokenize  (0) 2017.10.19
[CPP] Windows Service 간단하게 만들기  (0) 2017.10.17