Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2507 lines
65 KiB

  1. /*++
  2. * File name:
  3. * tclient.c
  4. * Contents:
  5. * Initialization code. Global feedback thread
  6. *
  7. * Copyright (C) 1998-1999 Microsoft Corp.
  8. *
  9. --*/
  10. #include "stdafx.h"
  11. #include <windows.h>
  12. #include <stdio.h>
  13. #include <malloc.h>
  14. #include <process.h>
  15. #include <string.h>
  16. #include <stdlib.h>
  17. #include <ctype.h>
  18. #include <direct.h>
  19. #include <winsock.h>
  20. #include <tchar.h>
  21. #define WIDE2ANSI(_p_, _s_) \
  22. if ( NULL != _s_ ) \
  23. { \
  24. size_t len = wcslen( _s_ ) + 1; \
  25. size_t wlen = sizeof(wchar_t) * len; \
  26. char *wc = (char *)_alloca( wlen ); \
  27. \
  28. WideCharToMultiByte( \
  29. CP_UTF8, 0, _s_, -1, wc, (int)wlen, NULL, NULL \
  30. ); \
  31. _p_ = wc; \
  32. } else { \
  33. _p_ = NULL; \
  34. }
  35. #include "tclient.h"
  36. #define PROTOCOLAPI __declspec(dllexport)
  37. #include "protocol.h"
  38. #include "queues.h"
  39. #include "bmpcache.h"
  40. #include "extraexp.h"
  41. #include "scfuncs.h"
  42. //
  43. // COM support.
  44. //
  45. #include "resource.h"
  46. #include "initguid.h"
  47. #include "tclientax.h"
  48. #include "tclientaxobj.h"
  49. #include <atlwin.cpp>
  50. #include <atlctl.cpp>
  51. #define IID_DEFINED
  52. #include "tclientax_i.c"
  53. CComModule _Module;
  54. BEGIN_OBJECT_MAP(ObjectMap)
  55. OBJECT_ENTRY(CLSID_CTClient, CTClientApi)
  56. END_OBJECT_MAP()
  57. //
  58. // Use C linkage for global data.
  59. //
  60. extern "C" {
  61. /*
  62. * stolen from tssec.h
  63. */
  64. VOID
  65. _stdcall
  66. TSRNG_Initialize(
  67. VOID
  68. );
  69. BOOL
  70. _stdcall
  71. TSRNG_GenerateRandomBits(
  72. LPBYTE pbRandomKey,
  73. DWORD dwRandomKeyLen
  74. );
  75. BOOL
  76. _stdcall
  77. EncryptDecryptLocalData50(
  78. LPBYTE pbData,
  79. DWORD dwDataLen,
  80. LPBYTE pbSalt,
  81. DWORD dwSaltLen
  82. );
  83. /*
  84. * Internal functions definitions
  85. */
  86. BOOL _RegisterWindow(VOID);
  87. LRESULT CALLBACK _FeedbackWndProc( HWND , UINT, WPARAM, LPARAM);
  88. BOOL _CreateFeedbackThread(VOID);
  89. VOID _DestroyFeedbackThread(VOID);
  90. VOID _CleanStuff(VOID);
  91. /*
  92. * Global data
  93. */
  94. OSVERSIONINFOEXW g_OsInfo;
  95. HWND g_hWindow = NULL; // Window handle for the feedback thread
  96. HINSTANCE g_hInstance = NULL; // Dll instance
  97. PWAIT4STRING g_pWaitQHead = NULL; // Linked list for waited events
  98. PFNPRINTMESSAGE g_pfnPrintMessage= NULL;// Trace function (from smclient)
  99. PCONNECTINFO g_pClientQHead = NULL; // LL of all threads
  100. HANDLE g_hThread = NULL; // Feedback Thread handle
  101. LPCRITICAL_SECTION g_lpcsGuardWaitQueue = NULL;
  102. // Guards the access to all
  103. // global variables
  104. // Some strings we are expecting and response actions
  105. // Those are used in SCConnect, _Logon and SCStart
  106. CHAR g_strConsoleExtension[ MAX_STRING_LENGTH ];
  107. // Ferit's extension for the
  108. // console
  109. // Low Speed option
  110. // Cache Bitmaps on disc option
  111. // by default, client will not run
  112. // in full screen
  113. INT g_ConnectionFlags = TSFLAG_COMPRESSION|TSFLAG_BITMAPCACHE|TSFLAG_DRIVES|TSFLAG_PORTS;
  114. // Apply translation so the english strings are human readable
  115. // when language packs are installed
  116. //
  117. INT g_bTranslateStrings = 0;
  118. /*++
  119. * Function:
  120. * InitDone
  121. *
  122. * Description:
  123. * Initialize/delete global data. Create/destroy
  124. * feedback thread
  125. *
  126. * Arguments:
  127. * hDllInst - Instance to the DLL
  128. * bInit - TRUE if initialize
  129. *
  130. * Return value:
  131. * TRUE if succeeds
  132. *
  133. --*/
  134. int InitDone(HINSTANCE hDllInst, int bInit)
  135. {
  136. int rv = TRUE;
  137. if (bInit)
  138. {
  139. WCHAR szMyLibName[_MAX_PATH];
  140. //
  141. // Initialize the COM module.
  142. //
  143. _Module.Init(ObjectMap, hDllInst);
  144. g_lpcsGuardWaitQueue = (LPCRITICAL_SECTION) malloc(sizeof(*g_lpcsGuardWaitQueue));
  145. if (!g_lpcsGuardWaitQueue)
  146. {
  147. rv = FALSE;
  148. goto exitpt;
  149. }
  150. // Overreference the library
  151. // The reason for that is beacuse an internal thread is created.
  152. // When the library trys to unload it can't kill that thread
  153. // and wait for its handle to get signaled, because
  154. // the thread itself wants to go to DllEntry and this
  155. // causes a deadlock. The best solution is to overreference the
  156. // handle so the library is unload at the end of the process
  157. if (!GetModuleFileNameW(hDllInst,
  158. szMyLibName,
  159. sizeof(szMyLibName) / sizeof(*szMyLibName)))
  160. {
  161. TRACE((ERROR_MESSAGE, "Can't overref the dll. Exit.\n"));
  162. free(g_lpcsGuardWaitQueue);
  163. rv = FALSE;
  164. goto exitpt;
  165. }
  166. else {
  167. szMyLibName[SIZEOF_ARRAY(szMyLibName) - 1] = 0;
  168. }
  169. if (!LoadLibraryW(szMyLibName))
  170. {
  171. TRACE((ERROR_MESSAGE, "Can't overref the dll. Exit.\n"));
  172. free(g_lpcsGuardWaitQueue);
  173. rv = FALSE;
  174. goto exitpt;
  175. }
  176. // get the OS info
  177. ZeroMemory(&g_OsInfo, sizeof(g_OsInfo));
  178. g_OsInfo.dwOSVersionInfoSize = sizeof(g_OsInfo);
  179. if (!GetVersionExW((LPOSVERSIONINFOW)&g_OsInfo))
  180. {
  181. //
  182. // Windows 9x does not support OSVERSIONINFOEX, so retry with
  183. // OSVERSIONINFO.
  184. //
  185. ZeroMemory(&g_OsInfo, sizeof(g_OsInfo));
  186. g_OsInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
  187. if (!GetVersionExW((LPOSVERSIONINFOW)&g_OsInfo))
  188. {
  189. TRACE((ERROR_MESSAGE, "GetVersionEx failed.Exit\n"));
  190. free(g_lpcsGuardWaitQueue);
  191. rv = FALSE;
  192. goto exitpt;
  193. }
  194. }
  195. g_hInstance = hDllInst;
  196. InitializeCriticalSection(g_lpcsGuardWaitQueue);
  197. InitCache();
  198. if (_RegisterWindow()) // If failed to register the window,
  199. _CreateFeedbackThread(); // means the feedback thread will
  200. // not work
  201. } else
  202. {
  203. if (g_pWaitQHead || g_pClientQHead)
  204. {
  205. TRACE((ERROR_MESSAGE,
  206. "The Library unload is unclean. Will try to fix this\n"));
  207. _CleanStuff();
  208. }
  209. _DestroyFeedbackThread();
  210. DeleteCache();
  211. if (g_lpcsGuardWaitQueue)
  212. {
  213. DeleteCriticalSection(g_lpcsGuardWaitQueue);
  214. free(g_lpcsGuardWaitQueue);
  215. }
  216. g_lpcsGuardWaitQueue = NULL;
  217. g_hInstance = NULL;
  218. g_pfnPrintMessage = NULL;
  219. //
  220. // Terminate the COM module.
  221. //
  222. _Module.Term();
  223. }
  224. exitpt:
  225. return rv;
  226. }
  227. #if 0
  228. VOID
  229. _ConvertAnsiToUnicode( LPWSTR wszDst, LPWSTR wszSrc )
  230. {
  231. #define _TOHEX(_d_) ((_d_ <= '9' && _d_ >= '0')?_d_ - '0': \
  232. (_d_ <= 'f' && _d_ >= 'a')?_d_ - 'a' + 10: \
  233. (_d_ <= 'F' && _d_ >= 'F')?_d_ - 'A' + 10:0)
  234. while( wszSrc[0] && wszSrc[1] && wszSrc[2] && wszSrc[3] )
  235. {
  236. *wszDst = (WCHAR)((_TOHEX(wszSrc[0]) << 4) + _TOHEX(wszSrc[1]) +
  237. (((_TOHEX(wszSrc[2]) << 4) + _TOHEX(wszSrc[3])) << 8));
  238. wszDst ++;
  239. wszSrc += 4;
  240. }
  241. *wszDst = 0;
  242. #undef _TOHEX
  243. }
  244. /*
  245. *
  246. * Wrappers for GetPrivateProfileW, on Win95 there's no UNICODE veriosn
  247. * of this function
  248. *
  249. */
  250. DWORD
  251. _WrpGetPrivateProfileStringW(
  252. LPCWSTR lpAppName,
  253. LPCWSTR lpKeyName,
  254. LPCWSTR lpDefault,
  255. LPWSTR lpReturnedString,
  256. DWORD nSize,
  257. LPCWSTR lpFileName)
  258. {
  259. DWORD rv = 0;
  260. CHAR szAppName[MAX_STRING_LENGTH];
  261. CHAR szKeyName[MAX_STRING_LENGTH];
  262. CHAR szDefault[MAX_STRING_LENGTH];
  263. CHAR szReturnedString[MAX_STRING_LENGTH];
  264. CHAR szReturnedStringNonExp[MAX_STRING_LENGTH];
  265. CHAR szFileName[MAX_STRING_LENGTH];
  266. LPWSTR szwReturnedString = NULL;
  267. ASSERT( 0 != nSize );
  268. if ( nSize < wcslen( lpDefault ))
  269. wcsncpy( lpReturnedString, lpDefault, nSize - 1 );
  270. else
  271. wcscpy( lpReturnedString, lpDefault );
  272. __try {
  273. szwReturnedString = (LPWSTR) alloca(( nSize + 1 ) * sizeof( WCHAR ));
  274. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  275. szwReturnedString = NULL;
  276. }
  277. if ( !szwReturnedString )
  278. goto exitpt;
  279. if (ISNT())
  280. {
  281. rv = GetPrivateProfileStringW(
  282. lpAppName,
  283. lpKeyName,
  284. lpDefault,
  285. szwReturnedString,
  286. nSize,
  287. lpFileName);
  288. if (rv)
  289. {
  290. goto exitpt;
  291. }
  292. }
  293. // Call the ANSI version
  294. _snprintf(szAppName, MAX_STRING_LENGTH, "%S", lpAppName);
  295. _snprintf(szKeyName, MAX_STRING_LENGTH, "%S", lpKeyName);
  296. _snprintf(szFileName, MAX_STRING_LENGTH, "%S", lpFileName);
  297. _snprintf(szDefault, MAX_STRING_LENGTH, "%S", lpDefault);
  298. rv = GetPrivateProfileStringA(
  299. szAppName,
  300. szKeyName,
  301. szDefault,
  302. szReturnedStringNonExp,
  303. sizeof(szReturnedString),
  304. szFileName);
  305. ExpandEnvironmentStringsA(
  306. szReturnedStringNonExp,
  307. szReturnedString,
  308. sizeof(szReturnedString)
  309. );
  310. _snwprintf(lpReturnedString, nSize, L"%S", szReturnedString);
  311. lpReturnedStrig[ nSize - 1 ] = 0;
  312. exitpt:
  313. if ( NULL != szwReturnedString )
  314. {
  315. // expand the string
  316. //
  317. ExpandEnvironmentStringsW(
  318. szwReturnedString,
  319. lpReturnedString,
  320. nSize
  321. );
  322. }
  323. if ( L'\\' == lpReturnedString[0] &&
  324. L'U' == towupper(lpReturnedString[1]))
  325. _ConvertAnsiToUnicode( lpReturnedString, lpReturnedString + 2 );
  326. return rv;
  327. }
  328. UINT
  329. _WrpGetPrivateProfileIntW(
  330. LPCWSTR lpAppName,
  331. LPCWSTR lpKeyName,
  332. INT nDefault,
  333. LPCWSTR lpFileName)
  334. {
  335. UINT rv = (UINT)-1;
  336. CHAR szAppName[MAX_STRING_LENGTH];
  337. CHAR szKeyName[MAX_STRING_LENGTH];
  338. CHAR szFileName[MAX_STRING_LENGTH];
  339. rv = GetPrivateProfileIntW(
  340. lpAppName,
  341. lpKeyName,
  342. nDefault,
  343. lpFileName);
  344. if (rv != (UINT)-1 && rv)
  345. goto exitpt;
  346. // Call the ANSI version
  347. _snprintf(szAppName, MAX_STRING_LENGTH, "%S", lpAppName);
  348. _snprintf(szKeyName, MAX_STRING_LENGTH, "%S", lpKeyName);
  349. _snprintf(szFileName, MAX_STRING_LENGTH, "%S", lpFileName);
  350. rv = GetPrivateProfileIntA(
  351. szAppName,
  352. szKeyName,
  353. nDefault,
  354. szFileName);
  355. exitpt:
  356. return rv;
  357. }
  358. LONG RegCreateKeyExWrp(
  359. HKEY hkey,
  360. LPCWSTR lpSubKey,
  361. DWORD Reserved,
  362. LPWSTR lpClass,
  363. DWORD dwOptions,
  364. REGSAM samDesired,
  365. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  366. PHKEY phkResult,
  367. PDWORD lpdwDisposition
  368. )
  369. {
  370. LONG rv;
  371. if (!ISWIN9X())
  372. {
  373. return RegCreateKeyExW( hkey, lpSubKey, Reserved,
  374. lpClass, dwOptions, samDesired,
  375. lpSecurityAttributes,
  376. phkResult,
  377. lpdwDisposition );
  378. }
  379. __try {
  380. CHAR *lpSubKeyA;
  381. CHAR *lpClassA;
  382. WIDE2ANSI( lpSubKeyA, lpSubKey );
  383. WIDE2ANSI( lpClassA, lpClass );
  384. rv = RegCreateKeyExA( hkey, lpSubKeyA, Reserved,
  385. lpClassA, dwOptions, samDesired,
  386. lpSecurityAttributes,
  387. phkResult,
  388. lpdwDisposition );
  389. } __except( (GetExceptionCode() == STATUS_STACK_OVERFLOW)?
  390. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH )
  391. {
  392. rv = ERROR_STACK_OVERFLOW;
  393. }
  394. return rv;
  395. }
  396. LONG
  397. RegSetValueExWrp(
  398. HKEY hkey,
  399. LPCWSTR lpValueName,
  400. DWORD reserved,
  401. DWORD dwType,
  402. CONST BYTE *lpData,
  403. DWORD cbData
  404. )
  405. {
  406. LONG rv;
  407. if (!ISWIN9X())
  408. {
  409. return RegSetValueEx(
  410. hkey, lpValueName, reserved, dwType, lpData, cbData );
  411. }
  412. __try {
  413. CHAR *lpValueNameA;
  414. CHAR *lpDataA;
  415. WIDE2ANSI( lpValueNameA, lpValueName );
  416. if ( REG_SZ == dwType )
  417. {
  418. WIDE2ANSI( lpDataA, ((LPCWSTR)lpData) );
  419. lpData = (CONST BYTE *)lpDataA;
  420. cbData = (DWORD)strlen( lpDataA );
  421. }
  422. rv = RegSetValueExA( hkey, lpValueNameA, reserved, dwType, lpData, cbData );
  423. } __except( (GetExceptionCode() == STATUS_STACK_OVERFLOW) ?
  424. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH )
  425. {
  426. rv = ERROR_STACK_OVERFLOW;
  427. }
  428. return rv;
  429. }
  430. LONG RegQueryValueExWrp(
  431. HKEY hKey, // handle to key
  432. LPCWSTR lpValueName, // value name
  433. PDWORD lpReserved, // reserved
  434. PDWORD lpType, // type buffer
  435. PBYTE lpData, // data buffer
  436. PDWORD lpcbData // size of data buffer
  437. )
  438. {
  439. LONG rv;
  440. if (!ISWIN9X())
  441. {
  442. return RegQueryValueEx( hKey, lpValueName, lpReserved, lpType, lpData, lpcbData );
  443. }
  444. __try {
  445. CHAR *lpValueNameA;
  446. WIDE2ANSI( lpValueNameA, lpValueName );
  447. rv = RegQueryValueExA( hKey, lpValueNameA, lpReserved, lpType, lpData, lpcbData );
  448. } __except( (GetExceptionCode() == STATUS_STACK_OVERFLOW) ?
  449. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH )
  450. {
  451. rv = ERROR_STACK_OVERFLOW;
  452. }
  453. return rv;
  454. }
  455. LONG
  456. RegDeleteKeyWrp(
  457. HKEY hkey,
  458. LPCWSTR lpSubKey
  459. )
  460. {
  461. LONG rv;
  462. if ( !ISWIN9X() )
  463. {
  464. return RegDeleteKeyW( hkey, lpSubKey );
  465. }
  466. __try {
  467. CHAR *lpSubKeyA;
  468. WIDE2ANSI( lpSubKeyA, lpSubKey );
  469. rv = RegDeleteKeyA( hkey, lpSubKeyA );
  470. } __except( (GetExceptionCode() == STATUS_STACK_OVERFLOW) ?
  471. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH )
  472. {
  473. rv = ERROR_STACK_OVERFLOW;
  474. }
  475. return rv;
  476. }
  477. INT
  478. GetClassNameWrp(
  479. HWND hwnd,
  480. LPWSTR szName,
  481. INT max
  482. )
  483. {
  484. LPSTR szNameA;
  485. INT maxA;
  486. INT rv;
  487. if ( !ISWIN9X() )
  488. {
  489. return GetClassNameW( hwnd, szName,max );
  490. }
  491. maxA = max / sizeof( WCHAR );
  492. __try {
  493. szNameA = (LPSTR)_alloca( maxA );
  494. } __except( EXCEPTION_EXECUTE_HANDLER )
  495. {
  496. SetLastError( ERROR_STACK_OVERFLOW );
  497. rv = 0;
  498. goto exitpt;
  499. }
  500. rv = GetClassNameA( hwnd, szNameA, maxA );
  501. MultiByteToWideChar( CP_UTF8, 0, szNameA, maxA, szName, max );
  502. exitpt:
  503. return rv;
  504. }
  505. INT
  506. GetWindowTextWrp(
  507. HWND hwnd,
  508. LPWSTR szText,
  509. INT max
  510. )
  511. {
  512. LPSTR szTextA;
  513. INT maxA;
  514. INT rv;
  515. if ( !ISWIN9X() )
  516. {
  517. return GetWindowTextW( hwnd, szText ,max );
  518. }
  519. maxA = max / sizeof( WCHAR );
  520. __try {
  521. szTextA = (LPSTR)_alloca( maxA );
  522. } __except( EXCEPTION_EXECUTE_HANDLER )
  523. {
  524. SetLastError( ERROR_STACK_OVERFLOW );
  525. rv = 0;
  526. goto exitpt;
  527. }
  528. rv = GetClassNameA( hwnd, szTextA, maxA );
  529. MultiByteToWideChar( CP_UTF8, 0, szTextA, maxA, szText, max );
  530. exitpt:
  531. return rv;
  532. }
  533. #endif // 0
  534. /*++
  535. * Function:
  536. * ConstructLogonString
  537. *
  538. * Description:
  539. * Constructs the client command line. The format is taken from
  540. * the INI file, supports the following parameters:
  541. * %srv% - destination server
  542. * %usr% - username
  543. * %psw% - password
  544. * %dom% - domain
  545. *
  546. * Arguments:
  547. *
  548. * Return value:
  549. * none
  550. *
  551. --*/
  552. VOID
  553. ConstructLogonString(
  554. LPCWSTR lpszServerName,
  555. LPCWSTR lpszUserName,
  556. LPCWSTR lpszPassword,
  557. LPCWSTR lpszDomain,
  558. LPWSTR szLine,
  559. DWORD dwSize,
  560. PCONFIGINFO pConfig
  561. )
  562. {
  563. DWORD_PTR dwFmtSize;
  564. LPWSTR szFmt;
  565. //
  566. // fix the parameters
  567. //
  568. if ( NULL == lpszServerName )
  569. lpszServerName = L"";
  570. if ( NULL == lpszUserName )
  571. lpszUserName = L"";
  572. if ( NULL == lpszPassword )
  573. lpszPassword = L"";
  574. if ( NULL == lpszDomain )
  575. lpszDomain = L"";
  576. if ( dwSize < 1 )
  577. return;
  578. if ( NULL == pConfig )
  579. return;
  580. szFmt = pConfig->strLogonFmt;
  581. dwFmtSize = wcslen( szFmt );
  582. for( ; 0 != dwFmtSize && dwSize > 1 ; )
  583. {
  584. //
  585. // optimize the code path
  586. //
  587. if ( L'%' != *szFmt )
  588. goto copy_char;
  589. if ( dwFmtSize >= 5 )
  590. {
  591. INT iNewLen;
  592. if ( !_wcsnicmp( szFmt, L"%srv%", 5 ))
  593. {
  594. iNewLen = _snwprintf( szLine, dwSize,
  595. L"%s", lpszServerName );
  596. if ( iNewLen < 0 )
  597. {
  598. break;
  599. }
  600. szLine += iNewLen;
  601. dwSize -= iNewLen;
  602. szFmt += 5;
  603. dwFmtSize -= 5;
  604. } else if ( !_wcsnicmp( szFmt, L"%usr%", 5 ))
  605. {
  606. iNewLen = _snwprintf( szLine, dwSize,
  607. L"%s", lpszUserName );
  608. if ( iNewLen < 0 )
  609. {
  610. break;
  611. }
  612. szLine += iNewLen;
  613. dwSize -= iNewLen;
  614. szFmt += 5;
  615. dwFmtSize -= 5;
  616. } else if ( !_wcsnicmp( szFmt, L"%psw%", 5 ))
  617. {
  618. iNewLen = _snwprintf( szLine, dwSize,
  619. L"%s", lpszPassword );
  620. if ( iNewLen < 0 )
  621. {
  622. break;
  623. }
  624. szLine += iNewLen;
  625. dwSize -= iNewLen;
  626. szFmt += 5;
  627. dwFmtSize -= 5;
  628. } else if ( !_wcsnicmp( szFmt, L"%dom%", 5 ))
  629. {
  630. iNewLen = _snwprintf( szLine, dwSize,
  631. L"%s", lpszDomain );
  632. if ( iNewLen < 0 )
  633. {
  634. break;
  635. }
  636. szLine += iNewLen;
  637. dwSize -= iNewLen;
  638. szFmt += 5;
  639. dwFmtSize -= 5;
  640. } else {
  641. goto copy_char;
  642. }
  643. continue;
  644. }
  645. copy_char:
  646. *szLine = *szFmt;
  647. szLine ++;
  648. szFmt ++;
  649. dwSize --;
  650. dwFmtSize --;
  651. }
  652. *szLine = 0;
  653. }
  654. /*++
  655. * Function:
  656. * ConstructCmdLine
  657. *
  658. * Description:
  659. * Constructs the client command line. The format is taken from
  660. * the INI file, supports the following parameters:
  661. * %img% - the client's image
  662. * %srv% - destination server
  663. * %usr% - username
  664. * %psw% - password
  665. * %dom% - domain
  666. * %hrs% - horizontal resolution
  667. * %vrs% - vertical resolution
  668. * %wnd% - tclient's window handle, for accepting feedback
  669. * %reg% - registry referrence
  670. * %app% - starting app
  671. * %cwd% - (UNSUPPORTED) working directory for the app
  672. * %con% - /console if TSFLAG_RCONSOLE is defined
  673. *
  674. * Arguments:
  675. *
  676. * Return value:
  677. * none
  678. *
  679. --*/
  680. VOID
  681. ConstructCmdLine(
  682. LPCWSTR lpszServerName,
  683. LPCWSTR lpszUserName,
  684. LPCWSTR lpszPassword,
  685. LPCWSTR lpszDomain,
  686. LPCWSTR lpszShell,
  687. IN const int xRes,
  688. IN const int yRes,
  689. IN const int ConnectionFlags,
  690. LPWSTR szCommandLine,
  691. DWORD dwCmdLineSize,
  692. PCONFIGINFO pConfig
  693. )
  694. {
  695. DWORD_PTR dwFmtSize;
  696. LPWSTR szFmt;
  697. //
  698. // fix the parameters
  699. //
  700. if ( NULL == lpszServerName )
  701. lpszServerName = L"";
  702. if ( NULL == lpszUserName )
  703. lpszUserName = L"";
  704. if ( NULL == lpszPassword )
  705. lpszPassword = L"";
  706. if ( NULL == lpszDomain )
  707. lpszDomain = L"";
  708. if ( NULL == lpszShell )
  709. lpszShell = L"";
  710. if ( dwCmdLineSize < 1 )
  711. return;
  712. if ( NULL == pConfig )
  713. return;
  714. szFmt = pConfig->strCmdLineFmt;
  715. dwFmtSize = wcslen( szFmt );
  716. for( ; 0 != dwFmtSize && dwCmdLineSize > 1 ; )
  717. {
  718. //
  719. // optimize the code path
  720. //
  721. if ( L'%' != *szFmt )
  722. goto copy_char;
  723. if ( dwFmtSize >= 5 )
  724. {
  725. INT iNewLen;
  726. if ( !_wcsnicmp( szFmt, L"%img%", 5 ))
  727. {
  728. iNewLen = _snwprintf( szCommandLine, dwCmdLineSize,
  729. L"%s", pConfig->strClientImg );
  730. if ( iNewLen < 0 )
  731. {
  732. break;
  733. }
  734. szCommandLine += iNewLen;
  735. dwCmdLineSize -= iNewLen;
  736. szFmt += 5;
  737. dwFmtSize -= 5;
  738. } else if ( !_wcsnicmp( szFmt, L"%srv%", 5 ))
  739. {
  740. iNewLen = _snwprintf( szCommandLine, dwCmdLineSize,
  741. L"%s", lpszServerName );
  742. if ( iNewLen < 0 )
  743. {
  744. break;
  745. }
  746. szCommandLine += iNewLen;
  747. dwCmdLineSize -= iNewLen;
  748. szFmt += 5;
  749. dwFmtSize -= 5;
  750. } else if ( !_wcsnicmp( szFmt, L"%usr%", 5 ))
  751. {
  752. iNewLen = _snwprintf( szCommandLine, dwCmdLineSize,
  753. L"%s", lpszUserName );
  754. if ( iNewLen < 0 )
  755. {
  756. break;
  757. }
  758. szCommandLine += iNewLen;
  759. dwCmdLineSize -= iNewLen;
  760. szFmt += 5;
  761. dwFmtSize -= 5;
  762. } else if ( !_wcsnicmp( szFmt, L"%psw%", 5 ))
  763. {
  764. iNewLen = _snwprintf( szCommandLine, dwCmdLineSize,
  765. L"%s", lpszPassword );
  766. if ( iNewLen < 0 )
  767. {
  768. break;
  769. }
  770. szCommandLine += iNewLen;
  771. dwCmdLineSize -= iNewLen;
  772. szFmt += 5;
  773. dwFmtSize -= 5;
  774. } else if ( !_wcsnicmp( szFmt, L"%dom%", 5 ))
  775. {
  776. iNewLen = _snwprintf( szCommandLine, dwCmdLineSize,
  777. L"%s", lpszDomain );
  778. if ( iNewLen < 0 )
  779. {
  780. break;
  781. }
  782. szCommandLine += iNewLen;
  783. dwCmdLineSize -= iNewLen;
  784. szFmt += 5;
  785. dwFmtSize -= 5;
  786. } else if ( !_wcsnicmp( szFmt, L"%hrs%", 5 ))
  787. {
  788. iNewLen = _snwprintf( szCommandLine, dwCmdLineSize,
  789. L"%d", xRes );
  790. if ( iNewLen < 0 )
  791. {
  792. break;
  793. }
  794. szCommandLine += iNewLen;
  795. dwCmdLineSize -= iNewLen;
  796. szFmt += 5;
  797. dwFmtSize -= 5;
  798. } else if ( !_wcsnicmp( szFmt, L"%vrs%", 5 ))
  799. {
  800. iNewLen = _snwprintf( szCommandLine, dwCmdLineSize,
  801. L"%d", yRes );
  802. if ( iNewLen < 0 )
  803. {
  804. break;
  805. }
  806. szCommandLine += iNewLen;
  807. dwCmdLineSize -= iNewLen;
  808. szFmt += 5;
  809. dwFmtSize -= 5;
  810. } else if ( !_wcsnicmp( szFmt, L"%con%", 5 ))
  811. {
  812. if (ConnectionFlags & TSFLAG_RCONSOLE)
  813. {
  814. iNewLen = _snwprintf( szCommandLine, dwCmdLineSize,
  815. L"-console" );
  816. if ( iNewLen < 0 )
  817. {
  818. break;
  819. }
  820. } else
  821. {
  822. iNewLen = 0;
  823. }
  824. szCommandLine += iNewLen;
  825. dwCmdLineSize -= iNewLen;
  826. szFmt += 5;
  827. dwFmtSize -= 5;
  828. } else if ( !_wcsnicmp( szFmt, L"%wnd%", 5 ))
  829. {
  830. iNewLen = _snwprintf( szCommandLine, dwCmdLineSize,
  831. #ifdef _WIN64
  832. L"%I64d",
  833. #else // !_WIN64
  834. L"%d",
  835. #endif // !_WIN64
  836. (LONG_PTR)g_hWindow );
  837. if ( iNewLen < 0 )
  838. {
  839. break;
  840. }
  841. szCommandLine += iNewLen;
  842. dwCmdLineSize -= iNewLen;
  843. szFmt += 5;
  844. dwFmtSize -= 5;
  845. } else if ( !_wcsnicmp( szFmt, L"%reg%", 5 ))
  846. {
  847. iNewLen = _snwprintf( szCommandLine, dwCmdLineSize,
  848. REG_FORMAT,
  849. GetCurrentProcessId(), GetCurrentThreadId());
  850. if ( iNewLen < 0 )
  851. {
  852. break;
  853. }
  854. szCommandLine += iNewLen;
  855. dwCmdLineSize -= iNewLen;
  856. szFmt += 5;
  857. dwFmtSize -= 5;
  858. } else if ( !_wcsnicmp( szFmt, L"%app%", 5 ))
  859. {
  860. iNewLen = _snwprintf( szCommandLine, dwCmdLineSize,
  861. L"%s", lpszShell );
  862. if ( iNewLen < 0 )
  863. {
  864. break;
  865. }
  866. szCommandLine += iNewLen;
  867. dwCmdLineSize -= iNewLen;
  868. szFmt += 5;
  869. dwFmtSize -= 5;
  870. } else {
  871. goto copy_char;
  872. }
  873. continue;
  874. }
  875. copy_char:
  876. *szCommandLine = *szFmt;
  877. szCommandLine ++;
  878. szFmt ++;
  879. dwCmdLineSize --;
  880. dwFmtSize --;
  881. }
  882. *szCommandLine = 0;
  883. }
  884. /*++
  885. * Function:
  886. * _FeedbackWndProc
  887. * Description:
  888. * Window proc wich dispatches messages containing feedback
  889. * The messages are usualy sent by RDP clients
  890. *
  891. --*/
  892. LRESULT CALLBACK _FeedbackWndProc( HWND hwnd,
  893. UINT uiMessage,
  894. WPARAM wParam,
  895. LPARAM lParam)
  896. {
  897. // HANDLE hMapF = NULL;
  898. switch (uiMessage)
  899. {
  900. case WM_FB_TEXTOUT:
  901. _TextOutReceived((DWORD)wParam, (HANDLE)lParam);
  902. break;
  903. case WM_FB_GLYPHOUT:
  904. _GlyphReceived((DWORD)wParam, (HANDLE)lParam);
  905. break;
  906. case WM_FB_DISCONNECT:
  907. _SetClientDead(lParam);
  908. _CheckForWorkerWaitingDisconnect(lParam);
  909. _CancelWaitingWorker(lParam);
  910. break;
  911. case WM_FB_CONNECT:
  912. _CheckForWorkerWaitingConnect((HWND)wParam, lParam);
  913. break;
  914. case WM_FB_LOGON:
  915. TRACE((INFO_MESSAGE, "LOGON event, session ID=%d\n",
  916. wParam));
  917. _SetSessionID(lParam, (UINT)wParam);
  918. break;
  919. break;
  920. case WM_FB_ACCEPTME:
  921. return (_CheckIsAcceptable(lParam, FALSE) != NULL);
  922. case WM_FB_REPLACEPID:
  923. return (_ReplaceProcessId( wParam, lParam ));
  924. #ifdef _RCLX
  925. case WM_WSOCK: // Windows socket messages
  926. RClx_DispatchWSockEvent((SOCKET)wParam, lParam);
  927. break;
  928. #endif // _RCLX
  929. case WM_DESTROY:
  930. PostQuitMessage(0);
  931. break;
  932. default:
  933. return DefWindowProcA(hwnd, uiMessage, wParam, lParam);
  934. }
  935. return 0;
  936. }
  937. /*++
  938. * Function:
  939. * _RegisterWindow
  940. * Description:
  941. * Resgisters window class for the feedback dispatcher
  942. * Arguments:
  943. * none
  944. * Return value:
  945. * TRUE on success
  946. *
  947. --*/
  948. BOOL _RegisterWindow(VOID)
  949. {
  950. WNDCLASSA wc;
  951. BOOL rv = FALSE;
  952. // DWORD dwLastErr;
  953. memset(&wc, 0, sizeof(wc));
  954. wc.lpfnWndProc = _FeedbackWndProc;
  955. wc.hInstance = g_hInstance;
  956. wc.lpszClassName = _TSTNAMEOFCLAS;
  957. if (!RegisterClassA (&wc) &&
  958. GetLastError() &&
  959. GetLastError() != ERROR_CLASS_ALREADY_EXISTS)
  960. {
  961. TRACE((ERROR_MESSAGE,
  962. "Can't register class. GetLastError=%d\n",
  963. GetLastError()));
  964. goto exitpt;
  965. }
  966. rv = TRUE;
  967. exitpt:
  968. return rv;
  969. }
  970. /*++
  971. * Function:
  972. * _GoFeedback
  973. * Description:
  974. * Main function for the feedback thread. The thread is created for the
  975. * lifetime of the DLL
  976. * Arguments:
  977. * lpParam is unused
  978. * Return value:
  979. * Thread exit code
  980. --*/
  981. DWORD WINAPI _GoFeedback(LPVOID lpParam)
  982. {
  983. MSG msg;
  984. UNREFERENCED_PARAMETER(lpParam);
  985. g_hWindow = CreateWindowA(
  986. _TSTNAMEOFCLAS,
  987. NULL, // Window name
  988. 0, // dwStyle
  989. 0, // x
  990. 0, // y
  991. 0, // nWidth
  992. 0, // nHeight
  993. NULL, // hWndParent
  994. NULL, // hMenu
  995. g_hInstance,
  996. NULL); // lpParam
  997. if (!g_hWindow)
  998. {
  999. TRACE((ERROR_MESSAGE, "No feedback window handle"));
  1000. goto exitpt;
  1001. } else {
  1002. #ifdef _RCLX
  1003. if (!RClx_Init())
  1004. TRACE((ERROR_MESSAGE, "Can't initialize RCLX\n"));
  1005. #endif // _RCLX
  1006. while (GetMessageA (&msg, NULL, 0, 0) && msg.message != WM_FB_END)
  1007. {
  1008. DispatchMessageA (&msg);
  1009. }
  1010. #ifdef _RCLX
  1011. RClx_Done();
  1012. #endif // _RCLX
  1013. }
  1014. TRACE((INFO_MESSAGE, "Window/Thread destroyed\n"));
  1015. FreeLibraryAndExitThread(g_hInstance, 0);
  1016. exitpt:
  1017. return 1;
  1018. }
  1019. VOID
  1020. SetAllowBackgroundInput(
  1021. VOID
  1022. )
  1023. {
  1024. DWORD ResId;
  1025. LONG sysrc;
  1026. HKEY key;
  1027. DWORD disposition;
  1028. ResId = 1;
  1029. // sysrc = RegCreateKeyExWrp(HKEY_CURRENT_USER,
  1030. sysrc = RegCreateKeyExW(HKEY_CURRENT_USER,
  1031. REG_BASE,
  1032. 0, /* reserved */
  1033. NULL, /* class */
  1034. REG_OPTION_NON_VOLATILE,
  1035. KEY_ALL_ACCESS,
  1036. NULL, /* security attributes */
  1037. &key,
  1038. &disposition);
  1039. if (sysrc != ERROR_SUCCESS)
  1040. {
  1041. TRACE((WARNING_MESSAGE, "RegCreateKeyEx failed, sysrc = %d\n", sysrc));
  1042. goto exitpt;
  1043. }
  1044. // sysrc = RegSetValueExWrp(key,
  1045. sysrc = RegSetValueExW(key,
  1046. ALLOW_BACKGROUND_INPUT,
  1047. 0,
  1048. REG_DWORD,
  1049. (LPBYTE)&ResId,
  1050. sizeof(ResId));
  1051. if (sysrc != ERROR_SUCCESS)
  1052. {
  1053. TRACE((WARNING_MESSAGE, "RegSetValue failed, status = %d\n", sysrc));
  1054. }
  1055. RegCloseKey(key);
  1056. exitpt:
  1057. ;
  1058. }
  1059. /*
  1060. * Disables prompting the user for redirected drives and ports (may be even more stuff)
  1061. *
  1062. */
  1063. BOOL
  1064. _DisablePrompting(
  1065. LPCWSTR szServerName,
  1066. INT ConnectionFlags
  1067. )
  1068. {
  1069. BOOL rv = FALSE;
  1070. LONG rc;
  1071. HKEY hKey = NULL;
  1072. DWORD dwType, dwSize, dwData, dwDisp;
  1073. DWORD dwPromptFlags = 0;
  1074. if ( ConnectionFlags & TSFLAG_DRIVES )
  1075. {
  1076. dwPromptFlags |= 1;
  1077. }
  1078. if ( ConnectionFlags & TSFLAG_PORTS )
  1079. {
  1080. dwPromptFlags |= 2;
  1081. }
  1082. if ( 0 == dwPromptFlags )
  1083. {
  1084. rv = TRUE;
  1085. goto exitpt;
  1086. }
  1087. // rc = RegCreateKeyExWrp(
  1088. rc = RegCreateKeyExW(
  1089. HKEY_CURRENT_USER,
  1090. REG_BASE L"\\LocalDevices",
  1091. 0, // options
  1092. NULL, // class
  1093. REG_OPTION_NON_VOLATILE,
  1094. KEY_ALL_ACCESS,
  1095. NULL, // security
  1096. &hKey,
  1097. &dwDisp
  1098. );
  1099. if ( ERROR_SUCCESS != rc )
  1100. {
  1101. TRACE(( WARNING_MESSAGE, "RegOpenKeyEx failed (%d).Can't disable user prompt\n", rc ));
  1102. goto exitpt;
  1103. }
  1104. dwSize = sizeof( dwData );
  1105. // rc = RegQueryValueExWrp(
  1106. rc = RegQueryValueExW(
  1107. hKey,
  1108. szServerName,
  1109. NULL, // reserved
  1110. &dwType,
  1111. (LPBYTE)&dwData,
  1112. &dwSize
  1113. );
  1114. if ( ERROR_SUCCESS != rc ||
  1115. REG_DWORD != dwType )
  1116. {
  1117. dwData = 0;
  1118. }
  1119. dwData |= dwPromptFlags;
  1120. // rc = RegSetValueExWrp(
  1121. rc = RegSetValueExW(
  1122. hKey,
  1123. szServerName,
  1124. 0,
  1125. REG_DWORD,
  1126. (LPBYTE)&dwData,
  1127. sizeof( dwData )
  1128. );
  1129. if ( ERROR_SUCCESS != rc )
  1130. {
  1131. TRACE(( WARNING_MESSAGE, "RegSetValueEx failed (%d). Can't disable user prompt\n", rc ));
  1132. }
  1133. rv = TRUE;
  1134. exitpt:
  1135. if ( NULL != hKey )
  1136. {
  1137. RegCloseKey( hKey );
  1138. }
  1139. return rv;
  1140. }
  1141. /*++
  1142. * Function:
  1143. * _SetClientRegistry
  1144. * Description:
  1145. * Sets the registry prior running RDP client
  1146. * The format of the key is: smclient_PID_TID
  1147. * PID is the process ID and TID is the thread ID
  1148. * This key is deleated after the client disconnects
  1149. * Arguments:
  1150. * lpszServerName - server to which the client will connect
  1151. * xRes, yRes - clients resolution
  1152. * bLowSpeed - low speed (compression) option
  1153. * bCacheBitmaps - cache the bitmaps to the disc option
  1154. * bFullScreen - the client will be in full screen mode
  1155. * ... - ...
  1156. * KeyboardHook - keyboard hook mode
  1157. * Called by:
  1158. * SCConnect
  1159. --*/
  1160. VOID
  1161. _SetClientRegistry(
  1162. LPCWSTR lpszServerName,
  1163. LPCWSTR lpszShell,
  1164. LPCWSTR lpszUsername,
  1165. LPCWSTR lpszPassword,
  1166. LPCWSTR lpszDomain,
  1167. INT xRes,
  1168. INT yRes,
  1169. INT Bpp,
  1170. INT AudioOpts,
  1171. PCONNECTINFO *ppCI,
  1172. INT ConnectionFlags,
  1173. INT KeyboardHook)
  1174. {
  1175. // const CHAR *pData;
  1176. // CHAR szServer[MAX_STRING_LENGTH];
  1177. // register int i;
  1178. LONG sysrc;
  1179. HKEY key;
  1180. DWORD disposition;
  1181. DWORD_PTR dataSize;
  1182. DWORD ResId;
  1183. WCHAR lpszRegistryEntry[4*MAX_STRING_LENGTH];
  1184. // RECT rcDesktop = {0, 0, 0, 0};
  1185. // INT desktopX, desktopY;
  1186. _snwprintf(lpszRegistryEntry, sizeof(lpszRegistryEntry)/sizeof( lpszRegistryEntry[0] ),
  1187. L"%s\\" REG_FORMAT,
  1188. REG_BASE, GetCurrentProcessId(), GetCurrentThreadId());
  1189. lpszRegistryEntry[ sizeof(lpszRegistryEntry)/sizeof( lpszRegistryEntry[0] ) - 1 ] = 0;
  1190. #if 0
  1191. // Get desktop size
  1192. GetWindowRect(GetDesktopWindow(), &rcDesktop);
  1193. desktopX = rcDesktop.right;
  1194. desktopY = rcDesktop.bottom;
  1195. // Adjust the resolution
  1196. if (desktopX < xRes || desktopY < yRes)
  1197. {
  1198. xRes = desktopX;
  1199. yRes = desktopY;
  1200. }
  1201. #endif
  1202. dataSize = ( wcslen(lpszServerName) + 1 ) * sizeof( WCHAR );
  1203. // Before starting ducati client set registry with server name
  1204. // sysrc = RegCreateKeyExWrp(HKEY_CURRENT_USER,
  1205. sysrc = RegCreateKeyExW(HKEY_CURRENT_USER,
  1206. lpszRegistryEntry,
  1207. 0, /* reserved */
  1208. NULL, /* class */
  1209. REG_OPTION_NON_VOLATILE,
  1210. KEY_ALL_ACCESS,
  1211. NULL, /* security attributes */
  1212. &key,
  1213. &disposition);
  1214. if (sysrc != ERROR_SUCCESS)
  1215. {
  1216. TRACE((WARNING_MESSAGE, "RegCreateKeyEx failed, sysrc = %d\n", sysrc));
  1217. goto exitpt;
  1218. }
  1219. // sysrc = RegSetValueExWrp(key,
  1220. sysrc = RegSetValueExW(key,
  1221. L"MRU0",
  1222. 0, // reserved
  1223. REG_SZ,
  1224. (LPBYTE)lpszServerName,
  1225. (DWORD)dataSize);
  1226. if (sysrc != ERROR_SUCCESS)
  1227. {
  1228. TRACE((WARNING_MESSAGE, "RegSetValue failed, status = %d\n", sysrc));
  1229. }
  1230. // Set alternative shell (if specified
  1231. if (lpszShell)
  1232. {
  1233. // sysrc = RegSetValueExWrp(key,
  1234. sysrc = RegSetValueExW(key,
  1235. TEXT("Alternate Shell 50"),
  1236. 0, // reserved
  1237. REG_BINARY,
  1238. (LPBYTE)lpszShell,
  1239. (DWORD)(wcslen(lpszShell) * sizeof(*lpszShell)));
  1240. if (sysrc != ERROR_SUCCESS)
  1241. {
  1242. TRACE((WARNING_MESSAGE, "RegSetValue failed, status = %d\n", sysrc));
  1243. }
  1244. }
  1245. // set user name
  1246. //
  1247. if (lpszUsername)
  1248. {
  1249. // sysrc = RegSetValueExWrp(key,
  1250. sysrc = RegSetValueExW(key,
  1251. TEXT("UserName 50"),
  1252. 0, // reserved
  1253. REG_BINARY,
  1254. (LPBYTE)lpszUsername,
  1255. (DWORD)(wcslen(lpszUsername) * sizeof(*lpszUsername)));
  1256. if (sysrc != ERROR_SUCCESS)
  1257. {
  1258. TRACE((WARNING_MESSAGE, "RegSetValue failed, status = %d\n", sysrc));
  1259. }
  1260. }
  1261. // domain
  1262. //
  1263. if (lpszDomain)
  1264. {
  1265. WCHAR szBuff[MAX_STRING_LENGTH];
  1266. //
  1267. // convert lpszDomain to lower case only
  1268. // to force UpdateSessionPDU to be send from the server
  1269. //
  1270. wcsncpy( szBuff, lpszDomain, MAX_STRING_LENGTH - 1 );
  1271. _wcslwr( szBuff );
  1272. // sysrc = RegSetValueExWrp(key,
  1273. sysrc = RegSetValueExW(key,
  1274. TEXT("Domain 50"),
  1275. 0, // reserved
  1276. REG_BINARY,
  1277. (LPBYTE)szBuff,
  1278. (DWORD)(wcslen(lpszDomain) * sizeof(*lpszDomain)));
  1279. if (sysrc != ERROR_SUCCESS)
  1280. {
  1281. TRACE((WARNING_MESSAGE, "RegSetValue failed, status = %d\n", sysrc));
  1282. }
  1283. }
  1284. // Set the resolution
  1285. if (xRes >= 1600 && yRes >= 1200) ResId = 4;
  1286. else if (xRes >= 1280 && yRes >= 1024) ResId = 3;
  1287. else if (xRes >= 1024 && yRes >= 768) ResId = 2;
  1288. else if (xRes >= 800 && yRes >= 600) ResId = 1;
  1289. else ResId = 0; // 640x480
  1290. // sysrc = RegSetValueExWrp(key,
  1291. sysrc = RegSetValueExW(key,
  1292. L"Desktop Size ID",
  1293. 0,
  1294. REG_DWORD,
  1295. (LPBYTE)&ResId,
  1296. sizeof(ResId));
  1297. if (sysrc != ERROR_SUCCESS)
  1298. {
  1299. TRACE((WARNING_MESSAGE, "RegSetValue failed, status = %d\n", sysrc));
  1300. }
  1301. ResId = 1;
  1302. // sysrc = RegSetValueExWrp(key,
  1303. sysrc = RegSetValueExW(key,
  1304. L"Auto Connect",
  1305. 0, // reserved
  1306. REG_DWORD,
  1307. (LPBYTE)&ResId,
  1308. sizeof(ResId));
  1309. if (sysrc != ERROR_SUCCESS)
  1310. {
  1311. TRACE((WARNING_MESSAGE, "RegSetValue failed, status = %d\n", sysrc));
  1312. }
  1313. if ( (*ppCI)->pConfigInfo->Autologon )
  1314. {
  1315. WCHAR szEncPwd[127];
  1316. UINT cb;
  1317. BYTE Salt[20];
  1318. // password
  1319. //
  1320. if ( NULL == lpszPassword )
  1321. goto skip_pwd;
  1322. TSRNG_Initialize();
  1323. TSRNG_GenerateRandomBits( Salt, sizeof( Salt ));
  1324. wcsncpy( szEncPwd, lpszPassword, sizeof( szEncPwd ) / sizeof( szEncPwd[0]) - 1 ); // BUGBUG: AV?
  1325. szEncPwd[ sizeof( szEncPwd ) / sizeof( szEncPwd[0] ) - 1 ] = 0;
  1326. cb = sizeof(szEncPwd);
  1327. EncryptDecryptLocalData50( (LPBYTE)szEncPwd, cb,
  1328. Salt, sizeof( Salt ));
  1329. // sysrc = RegSetValueExWrp(key,
  1330. sysrc = RegSetValueExW(key,
  1331. L"Salt 50",
  1332. 0, // reserved
  1333. REG_BINARY,
  1334. (LPBYTE)Salt,
  1335. sizeof( Salt ));
  1336. if (sysrc != ERROR_SUCCESS)
  1337. {
  1338. TRACE((WARNING_MESSAGE, "RegSetValue failed, status = %d\n",
  1339. sysrc));
  1340. }
  1341. // sysrc = RegSetValueExWrp(key,
  1342. sysrc = RegSetValueExW(key,
  1343. L"Password 50",
  1344. 0, // reserved
  1345. REG_BINARY,
  1346. (LPBYTE)szEncPwd,
  1347. cb);
  1348. if (sysrc != ERROR_SUCCESS)
  1349. {
  1350. TRACE((WARNING_MESSAGE, "RegSetValue failed, status = %d\n",
  1351. sysrc));
  1352. }
  1353. skip_pwd:
  1354. ResId = 1;
  1355. // sysrc = RegSetValueExWrp(key,
  1356. sysrc = RegSetValueExW(key,
  1357. L"AutoLogon 50",
  1358. 0, // reserved
  1359. REG_DWORD,
  1360. (LPBYTE)&ResId,
  1361. sizeof(ResId));
  1362. }
  1363. if (sysrc != ERROR_SUCCESS)
  1364. {
  1365. TRACE((WARNING_MESSAGE, "RegSetValue failed, status = %d\n", sysrc));
  1366. }
  1367. ResId = (ConnectionFlags & TSFLAG_BITMAPCACHE)?1:0;
  1368. // sysrc = RegSetValueExWrp(key,
  1369. sysrc = RegSetValueExW(key,
  1370. L"BitmapCachePersistEnable",
  1371. 0, // reserved
  1372. REG_DWORD,
  1373. (LPBYTE)&ResId,
  1374. sizeof(ResId));
  1375. if (sysrc != ERROR_SUCCESS)
  1376. {
  1377. TRACE((WARNING_MESSAGE, "RegSetValue failed, status = %d\n", sysrc));
  1378. }
  1379. ResId = (ConnectionFlags & TSFLAG_COMPRESSION)?1:0;
  1380. // sysrc = RegSetValueExWrp(key,
  1381. sysrc = RegSetValueExW(key,
  1382. L"Compression",
  1383. 0, // reserved
  1384. REG_DWORD,
  1385. (LPBYTE)&ResId,
  1386. sizeof(ResId));
  1387. if (sysrc != ERROR_SUCCESS)
  1388. {
  1389. TRACE((WARNING_MESSAGE, "RegSetValue failed, status = %d\n", sysrc));
  1390. }
  1391. if (ConnectionFlags & TSFLAG_FULLSCREEN)
  1392. {
  1393. ResId = 2;
  1394. // sysrc = RegSetValueExWrp(key,
  1395. sysrc = RegSetValueExW(key,
  1396. L"Screen Mode ID",
  1397. 0, // reserved
  1398. REG_DWORD,
  1399. (LPBYTE)&ResId,
  1400. sizeof(ResId));
  1401. if (sysrc != ERROR_SUCCESS)
  1402. {
  1403. TRACE((WARNING_MESSAGE,
  1404. "RegSetValue failed, status = %d\n", sysrc));
  1405. }
  1406. }
  1407. if (ConnectionFlags & TSFLAG_DRIVES)
  1408. {
  1409. ResId = 1;
  1410. // sysrc = RegSetValueExWrp(key,
  1411. sysrc = RegSetValueExW(key,
  1412. L"RedirectDrives",
  1413. 0, // reserved
  1414. REG_DWORD,
  1415. (LPBYTE)&ResId,
  1416. sizeof(ResId));
  1417. if (sysrc != ERROR_SUCCESS)
  1418. {
  1419. TRACE((WARNING_MESSAGE,
  1420. "RegSetValue failed, status = %d\n", sysrc));
  1421. }
  1422. }
  1423. if (ConnectionFlags & TSFLAG_PORTS)
  1424. {
  1425. ResId = 1;
  1426. // sysrc = RegSetValueExWrp(key,
  1427. sysrc = RegSetValueExW(key,
  1428. L"RedirectComPorts",
  1429. 0, // reserved
  1430. REG_DWORD,
  1431. (LPBYTE)&ResId,
  1432. sizeof(ResId));
  1433. if (sysrc != ERROR_SUCCESS)
  1434. {
  1435. TRACE((WARNING_MESSAGE,
  1436. "RegSetValue failed, status = %d\n", sysrc));
  1437. }
  1438. }
  1439. _DisablePrompting( lpszServerName, ConnectionFlags );
  1440. if ( 0 != Bpp )
  1441. {
  1442. DWORD dw = Bpp;
  1443. // sysrc = RegSetValueExWrp(
  1444. sysrc = RegSetValueExW(
  1445. key,
  1446. L"Session Bpp",
  1447. 0,
  1448. REG_DWORD,
  1449. (LPBYTE)&dw,
  1450. sizeof( dw ));
  1451. if (sysrc != ERROR_SUCCESS)
  1452. {
  1453. TRACE((WARNING_MESSAGE,
  1454. "RegSetValue failed, status = %d\n", sysrc));
  1455. }
  1456. }
  1457. if ( 0 != AudioOpts )
  1458. {
  1459. DWORD dw = AudioOpts;
  1460. // sysrc = RegSetValueExWrp(
  1461. sysrc = RegSetValueExW(
  1462. key,
  1463. L"AudioMode",
  1464. 0,
  1465. REG_DWORD,
  1466. (LPBYTE)&dw,
  1467. sizeof( dw ));
  1468. if (sysrc != ERROR_SUCCESS)
  1469. {
  1470. TRACE((WARNING_MESSAGE,
  1471. "RegSetValue failed, status = %d\n", sysrc));
  1472. }
  1473. }
  1474. //
  1475. // Set the keyboard-hook mode.
  1476. //
  1477. // sysrc = RegSetValueExWrp(
  1478. sysrc = RegSetValueExW(
  1479. key,
  1480. L"KeyboardHook",
  1481. 0,
  1482. REG_DWORD,
  1483. (LPBYTE)&KeyboardHook,
  1484. sizeof(KeyboardHook));
  1485. if (sysrc != ERROR_SUCCESS)
  1486. {
  1487. TRACE((WARNING_MESSAGE,
  1488. "RegSetValue failed, status = %d\n", sysrc));
  1489. }
  1490. RegCloseKey(key);
  1491. exitpt:
  1492. ;
  1493. }
  1494. /*++
  1495. * Function:
  1496. * _DeleteClientRegistry
  1497. * Description:
  1498. * Deletes the key set by _SetClientRegistry
  1499. * Called by:
  1500. * SCDisconnect
  1501. --*/
  1502. VOID _DeleteClientRegistry(PCONNECTINFO pCI)
  1503. {
  1504. WCHAR lpszRegistryEntry[4*MAX_STRING_LENGTH];
  1505. LONG sysrc;
  1506. _snwprintf(lpszRegistryEntry, sizeof(lpszRegistryEntry)/sizeof(lpszRegistryEntry[0]),
  1507. L"%s\\" REG_FORMAT,
  1508. REG_BASE, GetCurrentProcessId(), pCI->OwnerThreadId);
  1509. lpszRegistryEntry[ sizeof(lpszRegistryEntry)/sizeof(lpszRegistryEntry[0]) -1 ] = 0;
  1510. // sysrc = RegDeleteKeyWrp(HKEY_CURRENT_USER, lpszRegistryEntry);
  1511. sysrc = RegDeleteKeyW(HKEY_CURRENT_USER, lpszRegistryEntry);
  1512. if (sysrc != ERROR_SUCCESS)
  1513. {
  1514. TRACE((WARNING_MESSAGE, "RegDeleteKey failed, status = %d\n", sysrc));
  1515. }
  1516. }
  1517. /*++
  1518. * Function:
  1519. * _CreateFeedbackThread
  1520. * Description:
  1521. * Creates the feedback thread
  1522. * Called by:
  1523. * InitDone
  1524. --*/
  1525. BOOL _CreateFeedbackThread(VOID)
  1526. {
  1527. BOOL rv = TRUE;
  1528. // Register feedback window class
  1529. // WNDCLASS wc;
  1530. UINT dwThreadId;
  1531. // UINT dwLastErr;
  1532. g_hThread = (HANDLE)
  1533. _beginthreadex
  1534. (NULL,
  1535. 0,
  1536. (unsigned (__stdcall *)(void*))_GoFeedback,
  1537. NULL,
  1538. 0,
  1539. &dwThreadId);
  1540. if (!g_hThread) {
  1541. TRACE((ERROR_MESSAGE, "Couldn't create thread\n"));
  1542. rv = FALSE;
  1543. }
  1544. return rv;
  1545. }
  1546. /*++
  1547. * Function:
  1548. * _DestroyFeedbackThread
  1549. * Description:
  1550. * Destroys the thread created by _CreateFeedbackThread
  1551. * Called by:
  1552. * InitDone
  1553. --*/
  1554. VOID _DestroyFeedbackThread(VOID)
  1555. {
  1556. if (g_hThread)
  1557. {
  1558. // DWORD dwWait;
  1559. // CHAR szMyLibName[_MAX_PATH];
  1560. // Closing feedback thread
  1561. PostMessageA(g_hWindow, WM_FB_END, 0, 0);
  1562. TRACE((INFO_MESSAGE, "Closing DLL thread\n"));
  1563. // Dedstroy the window
  1564. DestroyWindow(g_hWindow);
  1565. // CloseHandle(g_hThread);
  1566. g_hThread = NULL;
  1567. }
  1568. }
  1569. /*++
  1570. * Function:
  1571. * _CleanStuff
  1572. * Description:
  1573. * Cleans the global queues. Closes any resources
  1574. * Called by:
  1575. * InitDone
  1576. --*/
  1577. VOID _CleanStuff(VOID)
  1578. {
  1579. // Thread safe, bacause is executed from DllEntry
  1580. while (g_pClientQHead)
  1581. {
  1582. TRACE((WARNING_MESSAGE, "Cleaning connection info: 0x%x\n",
  1583. g_pClientQHead));
  1584. SCDisconnect(g_pClientQHead);
  1585. }
  1586. #if 0
  1587. if (g_pClientQHead)
  1588. {
  1589. PCONNECTINFO pNext, pIter = g_pClientQHead;
  1590. while (pIter)
  1591. {
  1592. int nEv;
  1593. DWORD wres;
  1594. TRACE((WARNING_MESSAGE, "Cleaning connection info: 0x%x\n", pIter));
  1595. // Clear Events
  1596. if (pIter->evWait4Str)
  1597. {
  1598. CloseHandle(pIter->evWait4Str);
  1599. pIter->evWait4Str = NULL;
  1600. }
  1601. for (nEv = 0; nEv < pIter->nChatNum; nEv ++)
  1602. CloseHandle(pIter->aevChatSeq[nEv]);
  1603. pIter->nChatNum = 0;
  1604. // Clear Processes
  1605. do {
  1606. SendMessageA(pIter->hClient, WM_CLOSE, 0, 0);
  1607. } while((wres = WaitForSingleObject(pIter->hProcess, pCI->pConfigInfo->WAIT4STR_TIMEOUT/4) == WAIT_TIMEOUT));
  1608. if (wres == WAIT_TIMEOUT)
  1609. {
  1610. TRACE((WARNING_MESSAGE,
  1611. "Can't close process. WaitForSingleObject timeouts\n"));
  1612. TRACE((WARNING_MESSAGE,
  1613. "Process #%d will be killed\n",
  1614. pIter->dwProcessId ));
  1615. if (!TerminateProcess(pIter->hProcess, 1))
  1616. {
  1617. TRACE((WARNING_MESSAGE,
  1618. "Can't kill process #%d. GetLastError=%d\n",
  1619. pIter->dwProcessId, GetLastError()));
  1620. }
  1621. }
  1622. TRACE((WARNING_MESSAGE, "Closing process\n"));
  1623. if (pIter->hProcess)
  1624. CloseHandle(pIter->hProcess);
  1625. if (pIter->hThread)
  1626. CloseHandle(pIter->hThread);
  1627. pIter->hProcess = pIter->hThread = NULL;
  1628. // Free the structures
  1629. pNext = pIter->pNext;
  1630. free(pNext);
  1631. pIter = pNext;
  1632. }
  1633. }
  1634. #endif // 0
  1635. }
  1636. VOID _TClientAssert(BOOL bCond,
  1637. LPCSTR filename,
  1638. INT line,
  1639. LPCSTR expression,
  1640. BOOL bBreak)
  1641. {
  1642. if (!bCond)
  1643. {
  1644. TRACE((ERROR_MESSAGE,
  1645. "ASSERT (%s) %s line: %d\n",
  1646. expression,
  1647. filename,
  1648. line));
  1649. if (bBreak)
  1650. {
  1651. DebugBreak();
  1652. }
  1653. }
  1654. }
  1655. /*++
  1656. * Function:
  1657. * LoadSmClientFile
  1658. * Description:
  1659. * Loads the appropriate SMCLIENT.INI
  1660. * Called by:
  1661. * _FillConfigInfo
  1662. --*/
  1663. VOID LoadSmClientFile(WCHAR *szIniFileName, DWORD dwIniFileNameLen, LPSTR szLang)
  1664. {
  1665. WCHAR wszLang[4];
  1666. // Construct INI path
  1667. *szIniFileName = 0;
  1668. if(!_wgetcwd (
  1669. szIniFileName,
  1670. (int)(dwIniFileNameLen - wcslen(SMCLIENT_INI) - 8))
  1671. )
  1672. {
  1673. TRACE((ERROR_MESSAGE, "Current directory length too long.\n"));
  1674. }
  1675. if ( 0 == *szIniFileName )
  1676. {
  1677. CHAR szaIniFileName[_MAX_PATH];
  1678. TRACE((WARNING_MESSAGE, "Reading ASCII working dir\n"));
  1679. DWORD_PTR dwINILen = wcslen(SMCLIENT_INI);
  1680. if (!_getcwd (
  1681. szaIniFileName,
  1682. (int)(sizeof(szaIniFileName) - dwINILen - 8))
  1683. )
  1684. {
  1685. TRACE((ERROR_MESSAGE, "Current directory length too long.\n"));
  1686. }
  1687. else
  1688. {
  1689. _snwprintf(szIniFileName, dwIniFileNameLen, L"%S", szaIniFileName );
  1690. szIniFileName[ dwIniFileNameLen - 1 ] = 0;
  1691. }
  1692. if ( wcslen( szIniFileName ) > dwIniFileNameLen - wcslen(SMCLIENT_INI) - strlen(szLang) - 2 )
  1693. {
  1694. TRACE(( ERROR_MESSAGE, "Current directory length too long.\n"));
  1695. szIniFileName[0] = 0;
  1696. return;
  1697. }
  1698. }
  1699. // add '\' at the end if there isn't one
  1700. if (szIniFileName[wcslen(szIniFileName)-1]!=L'\\')
  1701. {
  1702. wcscat(szIniFileName, L"\\");
  1703. }
  1704. printf("Loading the smclient file \n");
  1705. wcscat(szIniFileName, SMCLIENT_INI);
  1706. if( strcmp( szLang, "0409") )
  1707. {
  1708. wcscat(szIniFileName, L".");
  1709. MultiByteToWideChar( CP_ACP, 0, szLang, -1, wszLang, sizeof(wszLang)/sizeof(wszLang[0]) );
  1710. wcscat(szIniFileName, wszLang);
  1711. }
  1712. ; //return VOID
  1713. }
  1714. /*++
  1715. * Function:
  1716. * _FillConfigInfo
  1717. *
  1718. * Description:
  1719. * Reads smclient.ini, section [tclient], variable "timeout"
  1720. * Also read some other values
  1721. * Arguments:
  1722. * PCONFIGINFO
  1723. * Return value:
  1724. * none
  1725. *
  1726. --*/
  1727. VOID _FillConfigInfo(PCONFIGINFO pConfigInfo) // LPSTR szLang)
  1728. {
  1729. UINT nNew;
  1730. WCHAR szIniFileName[_MAX_PATH];
  1731. // WCHAR szBuff[ 4 * MAX_STRING_LENGTH ];
  1732. WCHAR szBuffDef[MAX_STRING_LENGTH];
  1733. BOOL bFlag;
  1734. DWORD dwIniFileNameLen = _MAX_PATH;
  1735. /* Initializing variables here */
  1736. pConfigInfo->CONNECT_TIMEOUT = 35000;
  1737. pConfigInfo->ConnectionFlags = TSFLAG_COMPRESSION|TSFLAG_BITMAPCACHE;
  1738. pConfigInfo->Autologon = 0;
  1739. pConfigInfo->UseRegistry = 1;
  1740. pConfigInfo->LoginWait = 1;
  1741. pConfigInfo->bTranslateStrings = 0;
  1742. pConfigInfo->bUnicode = 0;
  1743. pConfigInfo->KeyboardHook = TCLIENT_KEYBOARD_HOOK_FULLSCREEN;
  1744. //
  1745. // Clear the configuration info and the INI-file name.
  1746. //
  1747. ZeroMemory(pConfigInfo, sizeof(*pConfigInfo));
  1748. ZeroMemory(szIniFileName, sizeof(szIniFileName));
  1749. // LoadSmClientFile(szIniFileName, _MAX_PATH, szLang);
  1750. if(!_wgetcwd (
  1751. szIniFileName,
  1752. (int)(dwIniFileNameLen - wcslen(SMCLIENT_INI) - 1))
  1753. )
  1754. {
  1755. TRACE((ERROR_MESSAGE, "Current directory length too long.\n"));
  1756. }
  1757. if ( 0 == *szIniFileName )
  1758. {
  1759. CHAR szaIniFileName[_MAX_PATH];
  1760. TRACE((WARNING_MESSAGE, "Reading ASCII working dir\n"));
  1761. DWORD_PTR dwINILen = wcslen(SMCLIENT_INI);
  1762. if (!_getcwd (
  1763. szaIniFileName,
  1764. (int)(sizeof(szaIniFileName) - dwINILen - 1))
  1765. )
  1766. {
  1767. TRACE((ERROR_MESSAGE, "Current directory length too long.\n"));
  1768. }
  1769. else
  1770. {
  1771. _snwprintf(szIniFileName, dwIniFileNameLen, L"%S", szaIniFileName );
  1772. szIniFileName[ dwIniFileNameLen - 1 ] = 0;
  1773. }
  1774. //if ( wcslen( szIniFileName ) > dwIniFileNameLen - wcslen(SMCLIENT_INI) - strlen(szLang) - 2 )
  1775. if ( wcslen( szIniFileName ) > dwIniFileNameLen - wcslen(SMCLIENT_INI) - 2 )
  1776. {
  1777. TRACE(( ERROR_MESSAGE, "Current directory length too long.\n"));
  1778. szIniFileName[0] = 0;
  1779. return;
  1780. }
  1781. }
  1782. // add '\' at the end if there isn't one
  1783. if (szIniFileName[wcslen(szIniFileName)-1]!=L'\\')
  1784. {
  1785. wcscat(szIniFileName, L"\\");
  1786. }
  1787. wcscat(szIniFileName, SMCLIENT_INI);
  1788. // nNew = _WrpGetPrivateProfileIntW(
  1789. nNew = GetPrivateProfileIntW(
  1790. TCLIENT_INI_SECTION,
  1791. L"timeout",
  1792. 600,
  1793. szIniFileName);
  1794. if (nNew)
  1795. {
  1796. pConfigInfo->WAIT4STR_TIMEOUT = nNew * 1000;
  1797. TRACE((INFO_MESSAGE, "New timeout: %d seconds\n", nNew));
  1798. }
  1799. // nNew = _WrpGetPrivateProfileIntW(
  1800. nNew = GetPrivateProfileIntW(
  1801. TCLIENT_INI_SECTION,
  1802. L"contimeout",
  1803. 35,
  1804. szIniFileName);
  1805. if (nNew)
  1806. {
  1807. pConfigInfo->CONNECT_TIMEOUT = nNew * 1000;
  1808. TRACE((INFO_MESSAGE, "New timeout: %d seconds\n", nNew));
  1809. }
  1810. pConfigInfo->Autologon =
  1811. // _WrpGetPrivateProfileIntW(
  1812. GetPrivateProfileIntW(
  1813. TCLIENT_INI_SECTION,
  1814. L"Autologon",
  1815. 0,
  1816. szIniFileName);
  1817. pConfigInfo->UseRegistry =
  1818. // _WrpGetPrivateProfileIntW(
  1819. GetPrivateProfileIntW(
  1820. TCLIENT_INI_SECTION,
  1821. L"UseRegistry",
  1822. 1,
  1823. szIniFileName);
  1824. pConfigInfo->LoginWait =
  1825. // _WrpGetPrivateProfileIntW(
  1826. GetPrivateProfileIntW(
  1827. TCLIENT_INI_SECTION,
  1828. L"LoginWait",
  1829. 1,
  1830. szIniFileName);
  1831. pConfigInfo->bTranslateStrings =
  1832. // _WrpGetPrivateProfileIntW(
  1833. GetPrivateProfileIntW(
  1834. TCLIENT_INI_SECTION,
  1835. L"TranslateStrings",
  1836. 0,
  1837. szIniFileName);
  1838. pConfigInfo->bUnicode =
  1839. // _WrpGetPrivateProfileIntW(
  1840. GetPrivateProfileIntW(
  1841. TCLIENT_INI_SECTION,
  1842. L"Unicode",
  1843. 0,
  1844. szIniFileName);
  1845. pConfigInfo->KeyboardHook =
  1846. // _WrpGetPrivateProfileIntW(
  1847. GetPrivateProfileIntW(
  1848. TCLIENT_INI_SECTION,
  1849. L"KeyboardHook",
  1850. 0,
  1851. szIniFileName);
  1852. pConfigInfo->ConnectionFlags = 0;
  1853. bFlag =
  1854. // _WrpGetPrivateProfileIntW(
  1855. GetPrivateProfileIntW(
  1856. TCLIENT_INI_SECTION,
  1857. L"LowSpeed",
  1858. 0,
  1859. szIniFileName);
  1860. if (bFlag)
  1861. pConfigInfo->ConnectionFlags |=TSFLAG_COMPRESSION;
  1862. bFlag =
  1863. // _WrpGetPrivateProfileIntW(
  1864. GetPrivateProfileIntW(
  1865. TCLIENT_INI_SECTION,
  1866. L"PersistentCache",
  1867. 0,
  1868. szIniFileName);
  1869. if (bFlag)
  1870. pConfigInfo->ConnectionFlags |=TSFLAG_BITMAPCACHE;
  1871. bFlag =
  1872. // _WrpGetPrivateProfileIntW(
  1873. GetPrivateProfileIntW(
  1874. TCLIENT_INI_SECTION,
  1875. L"FullScreen",
  1876. 0,
  1877. szIniFileName);
  1878. if (bFlag)
  1879. pConfigInfo->ConnectionFlags |=TSFLAG_FULLSCREEN;
  1880. // read the strings
  1881. // _WrpGetPrivateProfileStringW(
  1882. GetPrivateProfileStringW(
  1883. TCLIENT_INI_SECTION,
  1884. L"StartRun",
  1885. RUN_MENU,
  1886. pConfigInfo->strStartRun,
  1887. MAX_STRING_LENGTH,
  1888. szIniFileName);
  1889. // _WrpGetPrivateProfileStringW(
  1890. GetPrivateProfileStringW(
  1891. TCLIENT_INI_SECTION,
  1892. L"StartLogoff",
  1893. START_LOGOFF,
  1894. pConfigInfo->strStartLogoff,
  1895. MAX_STRING_LENGTH,
  1896. szIniFileName);
  1897. // _WrpGetPrivateProfileStringW(
  1898. GetPrivateProfileStringW(
  1899. TCLIENT_INI_SECTION,
  1900. L"StartRunAct",
  1901. RUN_ACT,
  1902. pConfigInfo->strStartRun_Act,
  1903. MAX_STRING_LENGTH,
  1904. szIniFileName);
  1905. // _WrpGetPrivateProfileStringW(
  1906. GetPrivateProfileStringW(
  1907. TCLIENT_INI_SECTION,
  1908. L"RunBox",
  1909. RUN_BOX,
  1910. pConfigInfo->strRunBox,
  1911. MAX_STRING_LENGTH,
  1912. szIniFileName);
  1913. // _WrpGetPrivateProfileStringW(
  1914. GetPrivateProfileStringW(
  1915. TCLIENT_INI_SECTION,
  1916. L"WinLogon",
  1917. WINLOGON_USERNAME,
  1918. pConfigInfo->strWinlogon,
  1919. MAX_STRING_LENGTH,
  1920. szIniFileName);
  1921. // _WrpGetPrivateProfileStringW(
  1922. GetPrivateProfileStringW(
  1923. TCLIENT_INI_SECTION,
  1924. L"WinLogonAct",
  1925. WINLOGON_ACT,
  1926. pConfigInfo->strWinlogon_Act,
  1927. MAX_STRING_LENGTH,
  1928. szIniFileName);
  1929. // _WrpGetPrivateProfileStringW(
  1930. GetPrivateProfileStringW(
  1931. TCLIENT_INI_SECTION,
  1932. L"PriorWinLogon",
  1933. PRIOR_WINLOGON,
  1934. pConfigInfo->strPriorWinlogon,
  1935. MAX_STRING_LENGTH,
  1936. szIniFileName);
  1937. // _WrpGetPrivateProfileStringW(
  1938. GetPrivateProfileStringW(
  1939. TCLIENT_INI_SECTION,
  1940. L"PriorWinLogonAct",
  1941. PRIOR_WINLOGON_ACT,
  1942. pConfigInfo->strPriorWinlogon_Act,
  1943. MAX_STRING_LENGTH,
  1944. szIniFileName);
  1945. // _WrpGetPrivateProfileStringW(
  1946. GetPrivateProfileStringW(
  1947. TCLIENT_INI_SECTION,
  1948. L"NoSmartcard",
  1949. NO_SMARTCARD_UI,
  1950. pConfigInfo->strNoSmartcard,
  1951. MAX_STRING_LENGTH,
  1952. szIniFileName);
  1953. // _WrpGetPrivateProfileStringW(
  1954. GetPrivateProfileStringW(
  1955. TCLIENT_INI_SECTION,
  1956. L"Smartcard",
  1957. SMARTCARD_UI,
  1958. pConfigInfo->strSmartcard,
  1959. MAX_STRING_LENGTH,
  1960. szIniFileName);
  1961. // _WrpGetPrivateProfileStringW(
  1962. GetPrivateProfileStringW(
  1963. TCLIENT_INI_SECTION,
  1964. L"SmartcardAct",
  1965. SMARTCARD_UI_ACT,
  1966. pConfigInfo->strSmartcard_Act,
  1967. MAX_STRING_LENGTH,
  1968. szIniFileName);
  1969. // _WrpGetPrivateProfileStringW(
  1970. GetPrivateProfileStringW(
  1971. TCLIENT_INI_SECTION,
  1972. L"LoginString",
  1973. L"",
  1974. pConfigInfo->strLogonFmt,
  1975. MAX_STRING_LENGTH,
  1976. szIniFileName);
  1977. // _WrpGetPrivateProfileStringW(
  1978. GetPrivateProfileStringW(
  1979. TCLIENT_INI_SECTION,
  1980. L"NTSecurity",
  1981. WINDOWS_NT_SECURITY,
  1982. pConfigInfo->strNTSecurity,
  1983. MAX_STRING_LENGTH,
  1984. szIniFileName);
  1985. // _WrpGetPrivateProfileStringW(
  1986. GetPrivateProfileStringW(
  1987. TCLIENT_INI_SECTION,
  1988. L"NTSecurityAct",
  1989. WINDOWS_NT_SECURITY_ACT,
  1990. pConfigInfo->strNTSecurity_Act,
  1991. MAX_STRING_LENGTH,
  1992. szIniFileName);
  1993. // _WrpGetPrivateProfileStringW(
  1994. GetPrivateProfileStringW(
  1995. TCLIENT_INI_SECTION,
  1996. L"SureLogoff",
  1997. ARE_YOU_SURE,
  1998. pConfigInfo->strSureLogoff,
  1999. MAX_STRING_LENGTH,
  2000. szIniFileName);
  2001. // _WrpGetPrivateProfileStringW(
  2002. GetPrivateProfileStringW(
  2003. TCLIENT_INI_SECTION,
  2004. L"SureLogoffAct",
  2005. SURE_LOGOFF_ACT,
  2006. pConfigInfo->strSureLogoffAct,
  2007. MAX_STRING_LENGTH,
  2008. szIniFileName);
  2009. // _WrpGetPrivateProfileStringW(
  2010. GetPrivateProfileStringW(
  2011. TCLIENT_INI_SECTION,
  2012. L"LogonErrorMessage",
  2013. LOGON_ERROR_MESSAGE,
  2014. pConfigInfo->strLogonErrorMessage,
  2015. MAX_STRING_LENGTH,
  2016. szIniFileName);
  2017. // _WrpGetPrivateProfileStringW(
  2018. GetPrivateProfileStringW(
  2019. TCLIENT_INI_SECTION,
  2020. L"LogonDisabled",
  2021. LOGON_DISABLED_MESSAGE,
  2022. pConfigInfo->strLogonDisabled,
  2023. MAX_STRING_LENGTH,
  2024. szIniFileName);
  2025. _snwprintf(szBuffDef, sizeof(szBuffDef) / sizeof( WCHAR ) , L"%S", CLIENT_CAPTION);
  2026. szBuffDef[MAX_STRING_LENGTH - 1] = 0;
  2027. // _WrpGetPrivateProfileStringW(
  2028. GetPrivateProfileStringW(
  2029. TCLIENT_INI_SECTION,
  2030. L"UIClientCaption",
  2031. szBuffDef,
  2032. pConfigInfo->strClientCaption,
  2033. MAX_STRING_LENGTH,
  2034. szIniFileName);
  2035. _snwprintf(szBuffDef, sizeof(szBuffDef) / sizeof( WCHAR ), L"%S", DISCONNECT_DIALOG_BOX);
  2036. szBuffDef[MAX_STRING_LENGTH - 1] = 0;
  2037. // _WrpGetPrivateProfileStringW(
  2038. GetPrivateProfileStringW(
  2039. TCLIENT_INI_SECTION,
  2040. L"UIDisconnectDialogBox",
  2041. szBuffDef,
  2042. pConfigInfo->strDisconnectDialogBox,
  2043. MAX_STRING_LENGTH,
  2044. szIniFileName);
  2045. _snwprintf(szBuffDef, sizeof(szBuffDef) / sizeof( WCHAR ), L"%S", YES_NO_SHUTDOWN);
  2046. szBuffDef[MAX_STRING_LENGTH - 1] = 0;
  2047. // _WrpGetPrivateProfileStringW(
  2048. GetPrivateProfileStringW(
  2049. TCLIENT_INI_SECTION,
  2050. L"UIYesNoDisconnect",
  2051. szBuffDef,
  2052. pConfigInfo->strYesNoShutdown,
  2053. MAX_STRING_LENGTH,
  2054. szIniFileName);
  2055. _snwprintf(szBuffDef, sizeof(szBuffDef) / sizeof( WCHAR ), L"%S", CLIENT_EXE);
  2056. szBuffDef[MAX_STRING_LENGTH - 1] = 0;
  2057. // _WrpGetPrivateProfileStringW(
  2058. GetPrivateProfileStringW(
  2059. TCLIENT_INI_SECTION,
  2060. L"ClientImage",
  2061. szBuffDef,
  2062. pConfigInfo->strClientImg,
  2063. MAX_STRING_LENGTH,
  2064. szIniFileName);
  2065. szBuffDef[0] = 0;
  2066. // _WrpGetPrivateProfileStringW(
  2067. GetPrivateProfileStringW(
  2068. TCLIENT_INI_SECTION,
  2069. L"ClientDebugger",
  2070. szBuffDef,
  2071. pConfigInfo->strDebugger,
  2072. MAX_STRING_LENGTH,
  2073. szIniFileName);
  2074. _snwprintf(szBuffDef, sizeof(szBuffDef) / sizeof( WCHAR ), L"%s", NAME_MAINCLASS);
  2075. szBuffDef[MAX_STRING_LENGTH - 1] = 0;
  2076. // _WrpGetPrivateProfileStringW(
  2077. GetPrivateProfileStringW(
  2078. TCLIENT_INI_SECTION,
  2079. L"UIMainWindowClass",
  2080. szBuffDef,
  2081. pConfigInfo->strMainWindowClass,
  2082. MAX_STRING_LENGTH,
  2083. szIniFileName);
  2084. // _WrpGetPrivateProfileStringW(
  2085. GetPrivateProfileStringW(
  2086. TCLIENT_INI_SECTION,
  2087. L"ClientCmdLine",
  2088. L"",
  2089. pConfigInfo->strCmdLineFmt,
  2090. 4 * MAX_STRING_LENGTH,
  2091. szIniFileName);
  2092. // _WrpGetPrivateProfileStringW(
  2093. GetPrivateProfileStringW(
  2094. TCLIENT_INI_SECTION,
  2095. L"ConsoleExtension",
  2096. L"",
  2097. pConfigInfo->strConsoleExtension,
  2098. MAX_STRING_LENGTH,
  2099. szIniFileName);
  2100. // _WrpGetPrivateProfileStringW(
  2101. GetPrivateProfileStringW(
  2102. TCLIENT_INI_SECTION,
  2103. L"sessionlist",
  2104. L"",
  2105. pConfigInfo->strSessionListDlg,
  2106. MAX_STRING_LENGTH,
  2107. szIniFileName);
  2108. }
  2109. /*++
  2110. * Function:
  2111. * DllCanUnloadNow
  2112. *
  2113. * Description:
  2114. * Used to determine whether the DLL can be unloaded by OLE
  2115. * Arguments:
  2116. * None.
  2117. * Return value:
  2118. * ...
  2119. *
  2120. --*/
  2121. STDAPI
  2122. DllCanUnloadNow(
  2123. VOID
  2124. )
  2125. {
  2126. return _Module.GetLockCount() == 0 ? S_OK : S_FALSE;
  2127. }
  2128. /////////////////////////////////////////////////////////////////////////////
  2129. /*++
  2130. * Function:
  2131. * DllGetClassObject
  2132. *
  2133. * Description:
  2134. * Returns a class factory to create an object of the requested type.
  2135. * Arguments:
  2136. * rclsid - ...
  2137. * riid - ...
  2138. * ppv - ...
  2139. * Return value:
  2140. * ...
  2141. *
  2142. --*/
  2143. STDAPI
  2144. DllGetClassObject(
  2145. IN REFCLSID rclsid,
  2146. IN REFIID riid,
  2147. OUT LPVOID* ppv
  2148. )
  2149. {
  2150. return _Module.GetClassObject(rclsid, riid, ppv);
  2151. }
  2152. /*++
  2153. * Function:
  2154. * DllRegisterServer
  2155. *
  2156. * Description:
  2157. * DllRegisterServer - Adds entries to the system registry
  2158. * Arguments:
  2159. * None.
  2160. * Return value:
  2161. * ...
  2162. *
  2163. --*/
  2164. STDAPI
  2165. DllRegisterServer(
  2166. VOID
  2167. )
  2168. {
  2169. // registers object, typelib and all interfaces in typelib
  2170. return _Module.RegisterServer(TRUE);
  2171. }
  2172. /*++
  2173. * Function:
  2174. * DllUnregisterServer
  2175. *
  2176. * Description:
  2177. * DllUnregisterServer - Removes entries from the system registry
  2178. * Arguments:
  2179. * None.
  2180. * Return value:
  2181. * ...
  2182. *
  2183. --*/
  2184. STDAPI
  2185. DllUnregisterServer(
  2186. VOID
  2187. )
  2188. {
  2189. _Module.UnregisterServer();
  2190. return S_OK;
  2191. }
  2192. } // extern "C"
  2193. #ifdef _M_IA64
  2194. //$WIN64: Don't know why _WndProcThunkProc isn't defined
  2195. extern "C" LRESULT CALLBACK _WndProcThunkProc(HWND, UINT, WPARAM, LPARAM)
  2196. {
  2197. return 0;
  2198. }
  2199. #endif