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.

492 lines
11 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation 1996-2001.
  5. //
  6. // File: wrapper.cpp
  7. //
  8. //----------------------------------------------------------------------------
  9. #include "stdafx.h"
  10. #include "util.h"
  11. #include "resource.h"
  12. #include "winreg.h"
  13. #include "areaprog.h"
  14. #include "wrapper.h"
  15. #include "dsgetdc.h"
  16. typedef DWORD (WINAPI *PFNDSGETDCNAME)(LPCWSTR, LPCWSTR, GUID *, LPCWSTR, ULONG, PDOMAIN_CONTROLLER_INFOW *);
  17. typedef struct {
  18. LPCWSTR szProfile;
  19. LPCWSTR szDatabase;
  20. LPCWSTR szLog;
  21. AREA_INFORMATION Area;
  22. LPVOID *pHandle;
  23. PSCE_AREA_CALLBACK_ROUTINE pCallback;
  24. HANDLE hWndCallback;
  25. DWORD dwFlags;
  26. } ENGINEARGS;
  27. BOOL
  28. PostProgressArea(
  29. IN HANDLE CallbackHandle,
  30. IN AREA_INFORMATION Area,
  31. IN DWORD TotalTicks,
  32. IN DWORD CurrentTicks
  33. );
  34. static BOOL bRangeSet=FALSE;
  35. CRITICAL_SECTION csOpenDatabase;
  36. #define OPEN_DATABASE_TIMEOUT INFINITE
  37. //
  38. // Helper functions to call the engine from a secondary thread:
  39. //
  40. DWORD WINAPI
  41. InspectSystemEx(LPVOID lpv) {
  42. if ( lpv == NULL ) return ERROR_INVALID_PARAMETER;
  43. ENGINEARGS *ea;
  44. SCESTATUS rc;
  45. ea = (ENGINEARGS *)lpv;
  46. DWORD dWarning=0;
  47. rc = SceAnalyzeSystem(NULL,
  48. ea->szProfile,
  49. ea->szDatabase,
  50. ea->szLog,
  51. SCE_UPDATE_DB|SCE_VERBOSE_LOG,
  52. ea->Area,
  53. ea->pCallback,
  54. ea->hWndCallback,
  55. &dWarning // this is required (by RPC)
  56. );
  57. return rc;
  58. }
  59. //
  60. // call to SCE engine to apply the template
  61. //
  62. DWORD WINAPI
  63. ApplyTemplateEx(LPVOID lpv) {
  64. if ( lpv == NULL ) return ERROR_INVALID_PARAMETER;
  65. ENGINEARGS *ea;
  66. SCESTATUS rc;
  67. ea = (ENGINEARGS *)lpv;
  68. rc = SceConfigureSystem(NULL,
  69. ea->szProfile,
  70. ea->szDatabase,
  71. ea->szLog,
  72. SCE_OVERWRITE_DB|SCE_VERBOSE_LOG,
  73. ea->Area,
  74. ea->pCallback,
  75. ea->hWndCallback,
  76. NULL
  77. );
  78. return rc;
  79. }
  80. WINBASEAPI
  81. BOOL
  82. WINAPI
  83. TryEnterCriticalSection(
  84. LPCRITICAL_SECTION lpCriticalSection
  85. );
  86. /*------------------------------------------------------------------------------
  87. Method: OpenDatabaseEx
  88. Synopsis: open database on a separate thread
  89. Arugments:
  90. Returns:
  91. History: a-mthoge 06-09-1998 - Added the _NT4BACK_PORT compile condition.
  92. ------------------------------------------------------------------------------*/
  93. DWORD
  94. WINAPI
  95. OpenDatabaseEx(LPVOID lpv) {
  96. if ( lpv == NULL ) return ERROR_INVALID_PARAMETER;
  97. ENGINEARGS *ea;
  98. SCESTATUS rc=0;
  99. if (TryEnterCriticalSection(&csOpenDatabase)) {
  100. ea = (ENGINEARGS *)lpv;
  101. rc = SceOpenProfile(ea->szProfile,
  102. (SCE_FORMAT_TYPE) ea->dwFlags, // SCE_JET_FORMAT || SCE_JET_ANALYSIS_REQUIRED
  103. ea->pHandle
  104. );
  105. LeaveCriticalSection(&csOpenDatabase);
  106. } else {
  107. rc = SCESTATUS_OTHER_ERROR;
  108. }
  109. return rc;
  110. }
  111. //
  112. // Assign a template to the system without configuring it
  113. //
  114. SCESTATUS
  115. AssignTemplate(LPCWSTR szTemplate,
  116. LPCWSTR szDatabase,
  117. BOOL bIncremental) {
  118. SCESTATUS rc;
  119. rc = SceConfigureSystem(NULL,
  120. szTemplate,
  121. szDatabase,
  122. NULL,
  123. (bIncremental ? SCE_UPDATE_DB : SCE_OVERWRITE_DB) | SCE_NO_CONFIG | SCE_VERBOSE_LOG,
  124. AREA_ALL,
  125. NULL,
  126. NULL,
  127. NULL
  128. );
  129. return rc;
  130. }
  131. //
  132. // apply a template to the system
  133. //
  134. DWORD
  135. ApplyTemplate(
  136. LPCWSTR szProfile,
  137. LPCWSTR szDatabase,
  138. LPCWSTR szLogFile,
  139. AREA_INFORMATION Area
  140. )
  141. {
  142. // Spawn a thread to call the engine & apply the profile, since this can
  143. // take a while and we want to stay responsive & have a change to provide
  144. // feedback.
  145. ENGINEARGS ea;
  146. HANDLE hThread=NULL;
  147. ea.szProfile = szProfile;
  148. ea.szDatabase = szDatabase;
  149. ea.szLog = szLogFile;
  150. ea.Area = Area;
  151. //
  152. // this is the progress call back dialog which
  153. // will be passed to SCE client stub for progress
  154. // callback
  155. //
  156. AreaProgress *ap = new AreaProgress;
  157. if ( ap ) {
  158. CString strTitle;
  159. CString strVerb;
  160. strTitle.LoadString(IDS_CONFIGURE_PROGRESS_TITLE);
  161. strVerb.LoadString(IDS_CONFIGURE_PROGRESS_VERB);
  162. ap->Create(IDD_ANALYZE_PROGRESS);
  163. ap->SetWindowText(strTitle);
  164. ap->SetDlgItemText(IDC_VERB,strVerb);
  165. ap->ShowWindow(SW_SHOW);
  166. bRangeSet = FALSE;
  167. }
  168. ea.pCallback = (PSCE_AREA_CALLBACK_ROUTINE)PostProgressArea;
  169. ea.hWndCallback = (HANDLE)ap;
  170. hThread = CreateThread(NULL,0,ApplyTemplateEx,&ea,0,NULL);
  171. DWORD dw=0;
  172. if ( hThread ) {
  173. MSG msg;
  174. DWORD dwTotalTicks=100;
  175. do {
  176. dw = MsgWaitForMultipleObjects(1,&hThread,0,INFINITE,QS_ALLINPUT);
  177. while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
  178. TranslateMessage(&msg);
  179. DispatchMessage(&msg);
  180. }
  181. } while (WAIT_OBJECT_0 != dw);
  182. GetExitCodeThread(hThread,&dw);
  183. CloseHandle(hThread);
  184. } else {
  185. dw = GetLastError();
  186. CString str;
  187. str.LoadString(IDS_CANT_CREATE_THREAD);
  188. AfxMessageBox(str);
  189. }
  190. //
  191. // free the dialog if it's created
  192. //
  193. if ( ap ) {
  194. if ( ap->GetSafeHwnd() )
  195. ap->DestroyWindow();
  196. delete ap;
  197. }
  198. return dw;
  199. }
  200. //
  201. // post progress
  202. //
  203. BOOL
  204. PostProgressArea(
  205. IN HANDLE CallbackHandle,
  206. IN AREA_INFORMATION Area,
  207. IN DWORD TotalTicks,
  208. IN DWORD CurrentTicks
  209. )
  210. {
  211. if ( CallbackHandle ) {
  212. AreaProgress *ap = (AreaProgress *)CallbackHandle;
  213. ap->ShowWindow(SW_SHOW);
  214. if ( !bRangeSet ) {
  215. ap->SetMaxTicks(TotalTicks);
  216. bRangeSet = TRUE;
  217. }
  218. ap->SetCurTicks(CurrentTicks);
  219. ap->SetArea(Area);
  220. return TRUE;
  221. } else {
  222. return FALSE;
  223. }
  224. }
  225. //
  226. // inspect a system
  227. //
  228. DWORD
  229. InspectSystem(
  230. LPCWSTR szProfile,
  231. LPCWSTR szDatabase,
  232. LPCWSTR szLogFile,
  233. AREA_INFORMATION Area
  234. )
  235. {
  236. // Spawn a thread to call the engine & inspect the system, since this can
  237. // take a while and we want to stay responsive & have a change to provide
  238. // feedback.
  239. ENGINEARGS ea;
  240. HANDLE hThread=NULL;
  241. ea.szProfile = szProfile;
  242. ea.szDatabase = szDatabase;
  243. ea.szLog = szLogFile;
  244. ea.Area = Area;
  245. AreaProgress *ap = new AreaProgress;
  246. if ( ap ) {
  247. ap->Create(IDD_ANALYZE_PROGRESS);
  248. ap->ShowWindow(SW_SHOW);
  249. bRangeSet = FALSE;
  250. }
  251. ea.pCallback = (PSCE_AREA_CALLBACK_ROUTINE)PostProgressArea;
  252. ea.hWndCallback = (HANDLE)ap;
  253. // return InspectSystemEx(&ea);
  254. hThread = CreateThread(NULL,0,InspectSystemEx,&ea,0,NULL);
  255. if (!hThread) {
  256. DWORD rc = GetLastError();
  257. CString str;
  258. str.LoadString(IDS_CANT_CREATE_THREAD);
  259. AfxMessageBox(str);
  260. // Display an error
  261. if ( ap ) {
  262. if ( ap->GetSafeHwnd() )
  263. ap->DestroyWindow();
  264. delete ap;
  265. }
  266. return rc;
  267. }
  268. MSG msg;
  269. DWORD dw=0;
  270. DWORD dwTotalTicks=100;
  271. int n = 0;
  272. do {
  273. dw = MsgWaitForMultipleObjects(1,&hThread,0,100,QS_ALLINPUT);
  274. while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
  275. TranslateMessage(&msg);
  276. DispatchMessage(&msg);
  277. }
  278. } while (WAIT_OBJECT_0 != dw);
  279. GetExitCodeThread(hThread,&dw);
  280. CloseHandle(hThread);
  281. if ( ap ) {
  282. if ( ap->GetSafeHwnd() )
  283. ap->DestroyWindow();
  284. delete ap;
  285. }
  286. return dw;
  287. }
  288. BOOL GetProfileDescription(LPCTSTR ProfileName, LPWSTR* Description)
  289. // Description must be freed by LocalFree
  290. // This should only be called for INF format profiles
  291. {
  292. PVOID hProfile=NULL;
  293. SCESTATUS rc;
  294. if (EngineOpenProfile(ProfileName,OPEN_PROFILE_CONFIGURE,&hProfile) == SCESTATUS_SUCCESS) {
  295. rc = SceGetScpProfileDescription(
  296. hProfile,
  297. Description);
  298. SceCloseProfile(&hProfile);
  299. if ( rc == SCESTATUS_SUCCESS ) {
  300. return(TRUE);
  301. } else {
  302. return(FALSE);
  303. }
  304. } else {
  305. return FALSE;
  306. }
  307. }
  308. SCESTATUS
  309. EngineOpenProfile(
  310. LPCWSTR FileName OPTIONAL,
  311. int format,
  312. PVOID* hProfile
  313. )
  314. {
  315. SCESTATUS status;
  316. ENGINEARGS ea;
  317. DWORD dw;
  318. HANDLE hThread=NULL;
  319. CString str;
  320. if ( !hProfile ) { // do not check !FileName because it's optional now
  321. return SCESTATUS_PROFILE_NOT_FOUND;
  322. }
  323. if ( (OPEN_PROFILE_LOCALPOL != format) &&
  324. !FileName ) {
  325. return SCESTATUS_PROFILE_NOT_FOUND;
  326. }
  327. ZeroMemory(&ea, sizeof( ENGINEARGS ) );
  328. // This is multithreaded for responsiveness, since a
  329. // crashed jet database can take forever and a day to open.
  330. // If we can open it quickly (where quickly is defined as within
  331. // OPEN_DATABASE_TIMEOUT milliseconds then
  332. if ( (OPEN_PROFILE_ANALYSIS == format) ||
  333. (OPEN_PROFILE_LOCALPOL == format)) {// JET {
  334. ea.szProfile = FileName;
  335. ea.pHandle = hProfile;
  336. if (OPEN_PROFILE_LOCALPOL == format) {
  337. ea.dwFlags = SCE_JET_FORMAT;
  338. } else {
  339. ea.dwFlags = SCE_JET_ANALYSIS_REQUIRED;
  340. }
  341. #if SPAWN_OPEN_DATABASE_THREAD
  342. hThread = CreateThread(NULL,0,OpenDatabaseEx,&ea,0,NULL);
  343. if ( hThread ) {
  344. dw = MsgWaitForMultipleObjects(1,&hThread,0,OPEN_DATABASE_TIMEOUT,0);
  345. if (WAIT_TIMEOUT == dw) {
  346. status = SCESTATUS_OTHER_ERROR;
  347. } else {
  348. GetExitCodeThread(hThread,&status);
  349. }
  350. CloseHandle(hThread);
  351. } else {
  352. status = GetLastError();
  353. }
  354. #else
  355. status = OpenDatabaseEx(&ea);
  356. #endif
  357. if( status != SCESTATUS_SUCCESS && *hProfile ){
  358. status = SCESTATUS_INVALID_DATA;
  359. }
  360. } else { // INF
  361. status = SceOpenProfile( FileName, SCE_INF_FORMAT, hProfile );
  362. }
  363. if ( status != SCESTATUS_SUCCESS ){
  364. *hProfile = NULL;
  365. }
  366. return status;
  367. }
  368. void EngineCloseProfile(PVOID* hProfile)
  369. {
  370. if ( hProfile ) {
  371. SceCloseProfile(hProfile);
  372. }
  373. }
  374. BOOL EngineGetDescription(PVOID hProfile, LPWSTR* Desc)
  375. {
  376. if ( SceGetScpProfileDescription( hProfile, Desc) != SCESTATUS_SUCCESS ) {
  377. return FALSE;
  378. } else {
  379. return TRUE;
  380. }
  381. }
  382. BOOL IsDomainController( LPCTSTR pszComputer )
  383. {
  384. //
  385. // for remote computers, connect to the remote registry
  386. // currently this api only works for local computer
  387. //
  388. SCE_SERVER_TYPE ServerType = SCESVR_UNKNOWN;
  389. SCESTATUS rc = SceGetServerProductType((LPTSTR)pszComputer, &ServerType);
  390. return ( (SCESTATUS_SUCCESS == rc) && (SCESVR_DC_WITH_DS == ServerType) );
  391. }