비스타 64비트에서 권한상승 ActiveX컨트롤을 불러오는 CoCreateInstanceAsAdmin()함수가 실패했다.
에러코드는 0x80080015 이다.
이유를 찾아보니 권한상승 컨트롤 등록시 "LocalizedString" 값이 누락된 경우 발생한다고 나와있다.
해서 레지스트리 편집기를 열어보니... 다음과 같이 되어 있었다.
LocalizedString @C:\Windows\System32\UpCtrl.dll,-101
왜 그럴까? 64비트 시스템 디렉토리로 다음과 같이 수동으로 바꿔 주니까 에러없이 잘 동작되었다.
LocalizedString @C:\Windows\SysWOW64\UpCtrl.dll,-101
권한상승 컨트롤 설치시 다음과 같은 코드를 넣어서 문제를 해결했다.
비스타 나온지도 오래 되었는데... 64비트는 이제야 설치해보고 테스트해보네..휴~
typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
LPFN_ISWOW64PROCESS
fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(_T("kernel32")), "IsWow64Process");
BOOL IsWow64()
{
BOOL bIsWow64 = FALSE;
if (NULL != fnIsWow64Process)
{
if (!fnIsWow64Process(GetCurrentProcess(), &bIsWow64))
{
// handle error
}
}
return bIsWow64;
}
STDAPI DllRegisterServer(void)
{
if (비스타운영체제면) {
...
//64비트 운영체제이면...
if (IsWow64())
{
TCHAR buf[MAX_PATH];
memset(buf, 0, sizeof(buf));
GetSystemWow64Directory(buf, MAX_PATH);
CString sBuf;
sBuf.Format(_T("@%s\\UpCtrl.dll,-101"), buf);
//MessageBox(NULL, sBuf.GetBuffer(0), _T("REG"), MB_OK);
HKEY hKey;
if (RegOpenKeyEx(HKEY_CLASSES_ROOT, _T("CLSID\\{YourClassID}"), 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
{
RegSetValueEx(hKey, _T("LocalizedString"), 0, REG_SZ, (const BYTE*)sBuf.GetBuffer(0), sBuf.GetLength()*sizeof(TCHAR));
RegCloseKey(hKey);
}
}
}
}
공부를 하나도 안 하니까... 자꾸 허접해지고 알던것도 다 까먹고,
정말 한심하군...
지금 바로 다시 볼 책
- TCP/IP 프로토콜, Forouzan
- TCP/IP volume1, Stevens
- Effective C++ 3판, 번역서
- More Effective C++, Meyers
- GOF 디자인패턴 활용서, 장세찬
새로 볼 책
- TCP/IP volume2, Stevens
- Essential C++, 번역서
- Effective STL, Meyers
- TCP/IP 라우팅 프로토콜, Jeff Doyle
올해 벌써 3월이 다 지나간다. 그래도 아직 9개월이나 남았네...
공부 좀 하자... 자꾸 다른거에 신경쓰지 말고,.. 위에 책들 꼭 다 보자.
내년엔 새로운 일 꼭 해야한다... 계속 가는거야!
응용프로그램을 윈도우즈 서비스로 등록할 수 있는 방법을 인터넷에서 찾아서 정리한다.
역시 인터넷에는 없는게 없구만...
- 등록
1. instsrv.exe와 srvany.exe 시스템 디렉토리로 복사
2. 컨맨드창에서 instsrv <service_name> srvany.exe
3. 레지스트리, HKLM\SYSTEM\Current Control Set\Services\<service_name>\Parameters 키 생성
3. [새로만들기]-[문자열값:REG_SZ]-[이름:Application 데이터는:해당경로] D:\service_name.exe"로 설정
4. 관리도구의 [서비스]를 열고 <service_name> 서비스에서 로그인탭의 서비스와 데스크톱 상호작용 허용을 체크한후에 서비스를 시작
- 제거
1. 컨맨드창에서 instsrv <service_name> remove
int listen(SOCKET s, int backlog);
소켓함수들중 listen 함수의 원형이다.
listen 함수를 호출하면 첫번째 인자로 된 소켓에 대해 리슨 대기큐를 backlog 크기만큼 만든다.
accept 함수를 호출하기 전까지 대기큐에 클라이언트로 부터 온 접속요청 entry가 리슨 대기큐에 쌓인다.
다음과 같이 호출하였다고 하면...
<서버>
...
if (listen(hServSock, 2)==SOCKET_ERROR)
ErrorHandling("listen() error");
...
<클라이언트>
for (int i=0; i<10; i++) {
hSocket[i]=socket(AF_INET, SOCK_STREAM, 0);
if (hSocket[i] == INVALID_SOCKET)
ErrorHandling("socket() error");
if (connect(hSocket[i], (SOCKADDR*)&servAddr, sizeof(servAddr))==SOCKET_ERROR)
ErrorHandling("connect() error");
}
서버에서는 listen 함수를 호출하고 accept 함수를 호출하기 전이다.
클라이언트에서는 서버로 연결할 소켓 10개를 생성한 후 10번 connect 호출하였다.
리슨 대기큐의 크기가 2이기 때문에 나머지 8번의 접속요청은 TCP에 의해 무시된다.
위의 과정을 자세히 풀어보면 클라이언트가 connect 함수를 호출함으로써 서버쪽 TCP는 SYN을 10개 받는다.
TCP 연결과정은 3-way handshaking 과정을 거친다. 처음 2번째까지의 SYN은 성공적으로 처리된다.
accept를 호출하지 않아도 연결상태가 연결로 바뀐다. 다음은 netstat 명령어로 2개의 연결된 상태를 보여준다.
나머지 8개의 SYN은 TCP에 의해 아예 무시된다. 서버쪽에서 아무런 응답패킷도 보내지 않기 때문에
클라이언트에서 보낸 나머지 8개의 연결요청은 타임아웃된다. 서버쪽에서 아래와 같이 호출하면 2번의
accept 함수는 성공적으로 리턴하고 그 다음 accept 함수는 리슨대기큐에 entry가 없기때문에 블럭킹된다.
이 상태에서 클라이언트에서 다시 연결요청을 하면 accept 함수는 리턴한다.
<서버>
for (int i=0; i<10; i++) {
clntAddrSize=sizeof(clntAddr);
hClntSock=accept(hServSock, (SOCKADDR*)&clntAddr,&clntAddrSize);
if (hClntSock==INVALID_SOCKET)
ErrorHandling("accept() error");
}
정리
1. listen 함수에서 backlog 크기만큼 리슨대기큐 생성
2. accept 함수에서 리슨대기큐에 쌓여 있는 연결요청 큐에서 빼오고 연결 소켓 생성
3. TCP 연결은 리슨대기큐에 쌓여 있는 연결요청만 처리, 큐에서 연결요청 entry를 제거하지 않음
4. 리슨대기큐가 작아서 무시된 연결 요청은 클라이언트쪽에서 타임아웃
5. 클라이언트 TCP는 연결요청 타임아웃되었기 때문에 다시 SYN 전송
이올린에 북마크하기
이올린에 추천하기
UserService.zip
