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.

1255 lines
41 KiB

  1. // ****************************************************************************
  2. //
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. //
  5. // Module Name:
  6. //
  7. // EventCreate.c
  8. //
  9. // Abstract:
  10. //
  11. // This modules implements creation of event in the user
  12. // specified log / application
  13. //
  14. // Syntax:
  15. // ------
  16. // EventCreate [-s server [-u username [-p password]]]
  17. // [-log name] [-source name] -id eventid -description description -type eventtype
  18. //
  19. // Author:
  20. //
  21. // Sunil G.V.N. Murali ([email protected]) 24-Sep-2000
  22. //
  23. // Revision History:
  24. //
  25. // Sunil G.V.N. Murali ([email protected]) 24-Sep-2000 : Created It.
  26. //
  27. // ****************************************************************************
  28. #include "pch.h"
  29. #include "EvcrtMsg.h"
  30. #include "EventCreate.h"
  31. //
  32. // constants / defines / enumerators
  33. //
  34. #define FULL_SUCCESS 0
  35. #define PARTIALLY_SUCCESS 1
  36. #define COMPLETELY_FAILED 1
  37. #define MAX_KEY_LENGTH 256
  38. #define EVENT_LOG_NAMES_LOCATION L"SYSTEM\\CurrentControlSet\\Services\\EventLog"
  39. // constants
  40. // NOTE: though the values in these variables are constants across
  41. // the tool, we are not marking them as contants on purpose.
  42. WCHAR g_wszDefaultLog[] = L"Application";
  43. WCHAR g_wszDefaultSource[] = L"EventCreate";
  44. typedef struct
  45. {
  46. // original buffers for command-line arguments
  47. BOOL bUsage;
  48. LPWSTR pwszServer;
  49. LPWSTR pwszUserName;
  50. LPWSTR pwszPassword;
  51. LPWSTR pwszLogName;
  52. LPWSTR pwszSource;
  53. LPWSTR pwszType;
  54. LPWSTR pwszDescription;
  55. DWORD dwEventID;
  56. // translations
  57. WORD wEventType;
  58. BOOL bCloseConnection;
  59. DWORD dwUserNameLength;
  60. DWORD dwPasswordLength;
  61. } TEVENTCREATE_PARAMS, *PTEVENTCREATE_PARAMS;
  62. //
  63. // function prototypes
  64. //
  65. BOOL Usage();
  66. BOOL CreateLogEvent( PTEVENTCREATE_PARAMS pParams );
  67. BOOL CheckExistence( PTEVENTCREATE_PARAMS pParams );
  68. BOOL UnInitializeGlobals( PTEVENTCREATE_PARAMS pParams );
  69. BOOL AddEventSource( HKEY hLogsKey, LPCWSTR pwszSource );
  70. BOOL ProcessOptions( LONG argc,
  71. LPCWSTR argv[],
  72. PTEVENTCREATE_PARAMS pParams, PBOOL pbNeedPwd );
  73. // ***************************************************************************
  74. // Routine Description:
  75. // This the entry point to this utility.
  76. //
  77. // Arguments:
  78. // [ in ] argc : argument(s) count specified at the command prompt
  79. // [ in ] argv : argument(s) specified at the command prompt
  80. //
  81. // Return Value:
  82. // The below are actually not return values but are the exit values
  83. // returned to the OS by this application
  84. // 0 : utility successfully created the events
  85. // 255 : utility completely failed in creating events
  86. // 128 : utility has partially successfull in creating events
  87. // ***************************************************************************
  88. DWORD _cdecl wmain( LONG argc, LPCWSTR argv[] )
  89. {
  90. // local variables
  91. BOOL bResult = FALSE;
  92. BOOL bNeedPassword = FALSE;
  93. TEVENTCREATE_PARAMS params;
  94. // init the structure to zero
  95. SecureZeroMemory( &params, sizeof( TEVENTCREATE_PARAMS ) );
  96. // process the command-line options
  97. bResult = ProcessOptions( argc, argv, &params, &bNeedPassword );
  98. // check the result of the parsing
  99. if ( bResult == FALSE )
  100. {
  101. // invalid syntax
  102. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  103. // exit from program
  104. UnInitializeGlobals( &params );
  105. return 1;
  106. }
  107. // check whether usage has to be displayed or not
  108. if ( params.bUsage == TRUE )
  109. {
  110. // show the usage of the utility
  111. Usage();
  112. // finally exit from the program
  113. UnInitializeGlobals( &params );
  114. return 0;
  115. }
  116. // ******
  117. // actual creation of events in respective log files will start from here
  118. // try establishing connection to the required terminal
  119. params.bCloseConnection = TRUE;
  120. bResult = EstablishConnection( params.pwszServer,
  121. params.pwszUserName, params.dwUserNameLength,
  122. params.pwszPassword, params.dwPasswordLength, bNeedPassword );
  123. if ( bResult == FALSE )
  124. {
  125. //
  126. // failed in establishing n/w connection
  127. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  128. // try with next server
  129. UnInitializeGlobals( &params );
  130. return 1;
  131. }
  132. else
  133. {
  134. // though the connection is successfull, some conflict might have occured
  135. switch( GetLastError() )
  136. {
  137. case I_NO_CLOSE_CONNECTION:
  138. params.bCloseConnection = FALSE;
  139. break;
  140. case E_LOCAL_CREDENTIALS:
  141. case ERROR_SESSION_CREDENTIAL_CONFLICT:
  142. {
  143. params.bCloseConnection = FALSE;
  144. ShowLastErrorEx( stderr, SLE_TYPE_WARNING | SLE_INTERNAL );
  145. break;
  146. }
  147. }
  148. }
  149. // report the log message
  150. bResult = CreateLogEvent( &params );
  151. if ( bResult == TRUE )
  152. {
  153. // both log and source would have specified
  154. if ( params.pwszSource != NULL && params.pwszLogName != NULL )
  155. {
  156. ShowMessage( stdout, L"\n" );
  157. ShowMessageEx( stdout, 2, TRUE, MSG_SUCCESS,
  158. params.pwszType, params.pwszLogName, params.pwszSource );
  159. }
  160. // only source name would have specified
  161. else if ( params.pwszSource != NULL )
  162. {
  163. ShowMessage( stdout, L"\n" );
  164. ShowMessageEx( stdout, 1, TRUE,
  165. MSG_SUCCESS_SOURCE, params.pwszType, params.pwszSource);
  166. }
  167. // only log name would have specified
  168. else if ( params.pwszLogName != NULL )
  169. {
  170. ShowMessage( stdout, L"\n" );
  171. ShowMessageEx( stdout, 1, TRUE,
  172. MSG_SUCCESS_LOG, params.pwszType, params.pwszLogName);
  173. }
  174. // nothing is specified -- can never be happened
  175. else
  176. {
  177. SetLastError( ERROR_PROCESS_ABORTED );
  178. ShowLastError( stderr );
  179. UnInitializeGlobals( &params );
  180. return 1;
  181. }
  182. }
  183. else
  184. {
  185. // display the message depending on the mode of conncetivity
  186. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  187. }
  188. // exit
  189. UnInitializeGlobals( &params );
  190. return ((bResult == TRUE) ? 0 : 1);
  191. }
  192. BOOL
  193. CreateLogEvent( PTEVENTCREATE_PARAMS pParams )
  194. /*++
  195. Routine Description:
  196. This function connects to the specified server's event log (or) source
  197. and appropriately creates the needed event in it.
  198. Arguments:
  199. Return Value:
  200. TRUE : if the event creation is successful
  201. FALSE : if failed in creating the event
  202. --*/
  203. {
  204. // local variables
  205. BOOL bReturn = 0; // return value
  206. HANDLE hEventLog = NULL; // points to the event log
  207. LPCWSTR pwszDescriptions[ 1 ] = { NULL }; // building descriptions
  208. HANDLE hToken = NULL; // Handle to the process token.
  209. PTOKEN_USER ptiUserName = NULL; // Structure to username info.
  210. DWORD dwUserLen = 0; // Buffer length of username SID.
  211. // check the input
  212. if ( pParams == NULL )
  213. {
  214. SetLastError( ERROR_PROCESS_ABORTED );
  215. SaveLastError();
  216. return FALSE;
  217. }
  218. //
  219. // start the process
  220. // extract the SID for the current logged on user -- in case of local machine
  221. // and SID for user specified with -u at the command prompt -- if not specified
  222. // get the current logged user SID only
  223. // check whether the log / source exists in the registry or not
  224. if ( CheckExistence( pParams ) == FALSE )
  225. {
  226. return FALSE; // return failure
  227. }
  228. // open the appropriate event log using the specified 'source' or 'log file'
  229. // and check the result of the operation
  230. // Note: At one time, we will make use of log name (or) source but not both
  231. if ( pParams->pwszSource != NULL )
  232. {
  233. // open log using source name
  234. hEventLog = RegisterEventSource( pParams->pwszServer, pParams->pwszSource );
  235. }
  236. else if ( pParams->pwszLogName != NULL )
  237. {
  238. // open log
  239. hEventLog = OpenEventLog( pParams->pwszServer, pParams->pwszLogName );
  240. }
  241. else
  242. {
  243. SetLastError( ERROR_PROCESS_ABORTED );
  244. SaveLastError();
  245. return FALSE;
  246. }
  247. // check the log open/register result
  248. if ( hEventLog == NULL )
  249. {
  250. // opening/registering is failed
  251. SaveLastError();
  252. return FALSE;
  253. }
  254. // Set boolean flag to FALSE.
  255. bReturn = FALSE;
  256. // Get handle to current process token.
  257. bReturn = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hToken );
  258. // Is 'OpenPrcessToken' successful.
  259. if ( TRUE == bReturn )
  260. {
  261. bReturn = FALSE;
  262. // Get buffer length, required to store the owner SID.
  263. GetTokenInformation( hToken, TokenUser, NULL, 0, &dwUserLen );
  264. // 'GetTokenInformation' fails because of insufficient buffer space.
  265. if( ERROR_INSUFFICIENT_BUFFER == GetLastError() )
  266. { // Assign memory and check whether it's allocated.
  267. ptiUserName = (PTOKEN_USER) AllocateMemory( dwUserLen + 1 );
  268. if( NULL != ptiUserName )
  269. { // Memory allocation is successful, get current process owber SID.
  270. bReturn = GetTokenInformation( hToken, TokenUser, ptiUserName, dwUserLen, &dwUserLen );
  271. if( TRUE == bReturn )
  272. { // Obtained the owner SID of current process.
  273. // report event
  274. pwszDescriptions[ 0 ] = pParams->pwszDescription;
  275. bReturn = ReportEvent( hEventLog, pParams->wEventType, 0,
  276. pParams->dwEventID, ptiUserName->User.Sid, 1, 0, pwszDescriptions, NULL);
  277. }
  278. }
  279. }
  280. }
  281. // check the result, save any error occured.
  282. if ( bReturn == FALSE )
  283. {
  284. // save the error info
  285. SaveLastError();
  286. }
  287. // Free handle to token and token info structure.
  288. if( NULL != hToken )
  289. {
  290. CloseHandle( hToken );
  291. }
  292. if( NULL != ptiUserName )
  293. {
  294. FreeMemory( &ptiUserName );
  295. }
  296. // close the event source
  297. if ( pParams->pwszSource != NULL )
  298. {
  299. DeregisterEventSource( hEventLog );
  300. }
  301. else
  302. {
  303. CloseEventLog( hEventLog );
  304. }
  305. // return the result
  306. return bReturn;
  307. }
  308. // ***************************************************************************
  309. // Routine Description:
  310. // This function checks wether the log name or source name specified
  311. // actually exists in the registry
  312. //
  313. // Arguments:
  314. // [ in ] szServer - server name
  315. // [ in ] szLog - log name
  316. // [ in ] szSource - source name
  317. //
  318. // Return Value:
  319. // TRUE : If log / source exists in the registry
  320. // FALSE : if failed find the match
  321. // ***************************************************************************
  322. BOOL CheckExistence( PTEVENTCREATE_PARAMS pParams )
  323. {
  324. // local variables
  325. DWORD dwSize = 0;
  326. LONG lResult = 0L;
  327. LPCWSTR pwsz = NULL;
  328. BOOL bCustom = FALSE;
  329. DWORD dwLogsIndex = 0;
  330. DWORD dwSourcesIndex = 0;
  331. BOOL bFoundMatch = FALSE;
  332. BOOL bDuplicating = FALSE;
  333. BOOL bErrorOccurred = FALSE;
  334. BOOL bLog = FALSE, bLogMatched = FALSE;
  335. BOOL bSource = FALSE, bSourceMatched = FALSE;
  336. HKEY hKey = NULL;
  337. HKEY hLogsKey = NULL;
  338. HKEY hSourcesKey = NULL;
  339. FILETIME ftLastWriteTime; // variable that will hold the last write info
  340. WCHAR wszRLog[ MAX_KEY_LENGTH ] = L"\0";
  341. WCHAR wszRSource[ MAX_KEY_LENGTH ] = L"\0";
  342. //
  343. // actual control flow starts
  344. //
  345. // check the input
  346. if ( pParams == NULL )
  347. {
  348. SetLastError( ERROR_PROCESS_ABORTED );
  349. SaveLastError();
  350. return FALSE;
  351. }
  352. // prepare the server name into UNC format
  353. pwsz = pParams->pwszServer;
  354. if ( pwsz != NULL && IsUNCFormat( pwsz ) == FALSE )
  355. {
  356. // format the server name in UNC format
  357. // NOTE: make use of the failure buffer to get the server name
  358. // in UNC format
  359. if ( SetReason2( 2, L"\\\\%s", pwsz ) == FALSE )
  360. {
  361. SaveLastError();
  362. return FALSE;
  363. }
  364. // ...
  365. pwsz = GetReason();
  366. }
  367. // Connect to the registry
  368. lResult = RegConnectRegistry( pwsz, HKEY_LOCAL_MACHINE, &hKey );
  369. if ( lResult != ERROR_SUCCESS)
  370. {
  371. // save the error information and return FAILURE
  372. SetLastError( lResult );
  373. SaveLastError();
  374. return FALSE;
  375. }
  376. // open the "EventLogs" registry key for enumerating its sub-keys (which are log names)
  377. lResult = RegOpenKeyEx( hKey, EVENT_LOG_NAMES_LOCATION, 0, KEY_READ, &hLogsKey );
  378. if ( lResult != ERROR_SUCCESS )
  379. {
  380. switch( lResult )
  381. {
  382. case ERROR_FILE_NOT_FOUND:
  383. SetLastError( ERROR_REGISTRY_CORRUPT );
  384. break;
  385. default:
  386. // save the error information and return FAILURE
  387. SetLastError( lResult );
  388. break;
  389. }
  390. // close the key and return
  391. SaveLastError();
  392. RegCloseKey( hKey );
  393. return FALSE;
  394. }
  395. // start enumerating the logs present
  396. dwLogsIndex = 0; // initialize the logs index
  397. bFoundMatch = FALSE; // assume neither log (or) source doesn't match
  398. bErrorOccurred = FALSE; // assume error is not occured
  399. dwSize = MAX_KEY_LENGTH; // max. size of the key buffer
  400. bLogMatched = FALSE;
  401. bSourceMatched = FALSE;
  402. bDuplicating = FALSE;
  403. ////////////////////////////////////////////////////////////////////////
  404. // Logic:-
  405. // 1. determine whether user has supplied the log name or not
  406. // 2. determine whether user has supplied the source name or not
  407. // 3. Start enumerating all the logs present in the system
  408. // 4. check whether log is supplied or not, if yes, check whether
  409. // the current log matches with user supplied one.
  410. // 5. check whether source is supplied or not, if yes, enumerate the
  411. // sources available under the current log
  412. // determine whether searching has to be done of LOG (or) SOURCE
  413. bLog = (pParams->pwszLogName != NULL) ? TRUE : FALSE; // #1
  414. bSource = (pParams->pwszSource != NULL) ? TRUE : FALSE; // #2
  415. // initiate the enumeration of log present in the system -- #3
  416. SecureZeroMemory( wszRLog, MAX_KEY_LENGTH * sizeof( WCHAR ) );
  417. lResult = RegEnumKeyEx( hLogsKey, 0, wszRLog,
  418. &dwSize, NULL, NULL, NULL, &ftLastWriteTime );
  419. // traverse thru the sub-keys until there are no more items -- #3
  420. do
  421. {
  422. // check the result
  423. if ( lResult != ERROR_SUCCESS )
  424. {
  425. // save the error and break from the loop
  426. bErrorOccurred = TRUE;
  427. SetLastError( lResult );
  428. SaveLastError();
  429. break;
  430. }
  431. // if log name is passed, compare the current key value
  432. // compare the log name with the current key -- #4
  433. if ( bLog == TRUE &&
  434. StringCompare( pParams->pwszLogName, wszRLog, TRUE, 0 ) == 0 )
  435. {
  436. bLogMatched = TRUE;
  437. }
  438. // if source name is passed ... -- #5
  439. if ( bSource == TRUE && bSourceMatched == FALSE )
  440. {
  441. // open the current log name to enumerate the sources under this log
  442. lResult = RegOpenKeyEx( hLogsKey, wszRLog, 0, KEY_READ, &hSourcesKey );
  443. if ( lResult != ERROR_SUCCESS )
  444. {
  445. // save the error and break from the loop
  446. bErrorOccurred = TRUE;
  447. SetLastError( lResult );
  448. SaveLastError();
  449. break;
  450. }
  451. // start enumerating the sources present
  452. dwSourcesIndex = 0; // initialize the sources index
  453. dwSize = MAX_KEY_LENGTH; // max. size of the key buffer
  454. SecureZeroMemory( wszRSource, dwSize * sizeof( WCHAR ) );
  455. lResult = RegEnumKeyEx( hSourcesKey, 0,
  456. wszRSource, &dwSize, NULL, NULL, NULL, &ftLastWriteTime );
  457. // traverse thru the sub-keys until there are no more items
  458. do
  459. {
  460. if ( lResult != ERROR_SUCCESS )
  461. {
  462. // save the error and break from the loop
  463. bErrorOccurred = TRUE;
  464. SetLastError( lResult );
  465. SaveLastError();
  466. break;
  467. }
  468. // check whether this key matches with the required source or not
  469. if ( StringCompare( pParams->pwszSource, wszRSource, TRUE, 0 ) == 0 )
  470. {
  471. // source matched
  472. bSourceMatched = TRUE;
  473. break; // break from the loop
  474. }
  475. // update the sources index and fetch the next source key
  476. dwSourcesIndex += 1;
  477. dwSize = MAX_KEY_LENGTH; // max. size of the key buffer
  478. SecureZeroMemory( wszRSource, dwSize * sizeof( WCHAR ) );
  479. lResult = RegEnumKeyEx( hSourcesKey, dwSourcesIndex,
  480. wszRSource, &dwSize, NULL, NULL, NULL, &ftLastWriteTime );
  481. } while( lResult != ERROR_NO_MORE_ITEMS );
  482. // close the sources registry key
  483. RegCloseKey( hSourcesKey );
  484. hSourcesKey = NULL; // clear the key value
  485. // check how the loop ended
  486. // 1. Source might have found
  487. // Action:- we found required key .. exit from the main loop
  488. // 2. Error might have occured
  489. // Action:- ignore the error and continue fetching other
  490. // log's sources
  491. // 3. End of sources reached in this log
  492. // Action:- check if log name is supplied or not.
  493. // if log specified, then source if not found, break
  494. // for cases 2 & 3, clear the contents of lResult for smooth processing
  495. // Case #2 & #3
  496. lResult = 0; // we are not much bothered abt the errors
  497. bErrorOccurred = FALSE; // occured while traversing thru the source under logs
  498. // Case #1
  499. if ( bSourceMatched == TRUE )
  500. {
  501. // check whether log is specified or not
  502. // if log is specified, it should have matched .. otherwise
  503. // error ... because duplicate source should not be created
  504. if ( bLog == FALSE ||
  505. ( bLog == TRUE &&
  506. bLogMatched == TRUE &&
  507. StringCompare(pParams->pwszLogName, wszRLog, TRUE, 0) == 0 ) )
  508. {
  509. // no problem ...
  510. bFoundMatch = TRUE;
  511. //
  512. // determine whether this is custom created source or not
  513. // mark this as custom source
  514. bCustom = FALSE;
  515. // open the source registry key
  516. // NOTE: make use of the failure buffer as temp buffer for
  517. // formatting
  518. if ( SetReason2( 3,
  519. L"%s\\%s\\%s",
  520. EVENT_LOG_NAMES_LOCATION,
  521. wszRLog, wszRSource ) == FALSE )
  522. {
  523. SaveLastError();
  524. bErrorOccurred = TRUE;
  525. break;
  526. }
  527. pwsz = GetReason();
  528. lResult = RegOpenKeyEx( hKey, pwsz,
  529. 0, KEY_QUERY_VALUE, &hSourcesKey );
  530. if ( lResult != ERROR_SUCCESS )
  531. {
  532. SetLastError( lResult );
  533. SaveLastError();
  534. bErrorOccurred = TRUE;
  535. break;
  536. }
  537. // now query for the value
  538. lResult = RegQueryValueEx( hSourcesKey,
  539. L"CustomSource", NULL, NULL, NULL, NULL );
  540. if ( lResult != ERROR_SUCCESS &&
  541. lResult != ERROR_FILE_NOT_FOUND )
  542. {
  543. RegCloseKey( hSourcesKey );
  544. SetLastError( lResult );
  545. SaveLastError();
  546. bErrorOccurred = TRUE;
  547. break;
  548. }
  549. // close the souces key
  550. RegCloseKey( hSourcesKey );
  551. // mark this as custom source
  552. if ( lResult == ERROR_SUCCESS )
  553. {
  554. bCustom = TRUE;
  555. }
  556. // break from the loop
  557. break;
  558. }
  559. else
  560. {
  561. // this should not be the case .. sources should not be duplicated
  562. SetReason2( 1, ERROR_SOURCE_DUPLICATING, wszRLog );
  563. bDuplicating = TRUE;
  564. }
  565. }
  566. }
  567. else if ( bLogMatched == TRUE && bSource == FALSE )
  568. {
  569. // mark this as a custom event source
  570. bCustom = TRUE;
  571. // ...
  572. bFoundMatch = TRUE;
  573. break;
  574. }
  575. else if ( bLogMatched == TRUE && bDuplicating == TRUE )
  576. {
  577. bErrorOccurred = TRUE;
  578. break;
  579. }
  580. // update the sources index and fetch the next log key
  581. dwLogsIndex += 1;
  582. dwSize = MAX_KEY_LENGTH; // max. size of the key buffer
  583. SecureZeroMemory( wszRLog, dwSize * sizeof( WCHAR ) );
  584. lResult = RegEnumKeyEx( hLogsKey, dwLogsIndex,
  585. wszRLog, &dwSize, NULL, NULL, NULL, &ftLastWriteTime );
  586. } while( lResult != ERROR_NO_MORE_ITEMS );
  587. // close the logs registry key
  588. RegCloseKey( hLogsKey );
  589. hLogsKey = NULL;
  590. // check whether any error has occured or not in doing above tasks
  591. if ( bErrorOccurred == TRUE )
  592. {
  593. // close the still opened registry keys
  594. RegCloseKey( hKey );
  595. hKey = NULL;
  596. // return failure
  597. return FALSE;
  598. }
  599. // now check whether location for creating the event is found or not
  600. // if not, check for the possibilities to create the source at appropriate location
  601. // NOTE:-
  602. // we won't create the logs. also to create the source, user needs to specify
  603. // the log name in which this source needs to be created.
  604. if ( bFoundMatch == FALSE )
  605. {
  606. if ( bLog == TRUE && bLogMatched == FALSE )
  607. {
  608. // log itself was not found ... error message
  609. SetReason2( 1, ERROR_LOG_NOTEXISTS, pParams->pwszLogName );
  610. }
  611. else if ( bLog == TRUE && bSource == TRUE &&
  612. bLogMatched == TRUE && bSourceMatched == FALSE )
  613. {
  614. //
  615. // log name and source both were supplied but only log was found
  616. // so create the source in it
  617. // open the "EventLogs\{logname}" registry key for creating new source
  618. // NOTE: we will make use of failure buffer to do the formatting
  619. if ( SetReason2( 2, L"%s\\%s",
  620. EVENT_LOG_NAMES_LOCATION, pParams->pwszLogName ) == FALSE )
  621. {
  622. SaveLastError();
  623. return FALSE;
  624. }
  625. pwsz = GetReason();
  626. lResult = RegOpenKeyEx( hKey, pwsz, 0, KEY_WRITE, &hLogsKey );
  627. if ( lResult != ERROR_SUCCESS )
  628. {
  629. switch( lResult )
  630. {
  631. case ERROR_FILE_NOT_FOUND:
  632. SetLastError( ERROR_REGISTRY_CORRUPT );
  633. break;
  634. default:
  635. // save the error information and return FAILURE
  636. SetLastError( lResult );
  637. break;
  638. }
  639. // close the key and return
  640. SaveLastError();
  641. RegCloseKey( hKey );
  642. return FALSE;
  643. }
  644. // now create the subkey with the source name given
  645. if ( AddEventSource( hLogsKey, pParams->pwszSource ) == FALSE )
  646. {
  647. RegCloseKey( hKey );
  648. RegCloseKey( hLogsKey );
  649. return FALSE;
  650. }
  651. // creation of new source is successfull
  652. bFoundMatch = TRUE;
  653. RegCloseKey( hSourcesKey );
  654. RegCloseKey( hLogsKey );
  655. // mark this as a custom event source
  656. bCustom = TRUE;
  657. }
  658. else if ( bLog == FALSE && bSource == TRUE && bSourceMatched == FALSE )
  659. {
  660. // else we need both log name and source in order to create the source
  661. SetReason( ERROR_NEED_LOG_ALSO );
  662. }
  663. }
  664. // check whether the source is custom create or pre-existing source
  665. if ( bFoundMatch == TRUE && bCustom == FALSE )
  666. {
  667. // we wont create events in a non-custom source
  668. SetReason( ERROR_NONCUSTOM_SOURCE );
  669. return FALSE;
  670. }
  671. // close the currently open registry keys
  672. RegCloseKey( hKey );
  673. // return the result
  674. return bFoundMatch;
  675. }
  676. // ***************************************************************************
  677. // Routine Description:
  678. // This function adds a new source to under the specifie log
  679. //
  680. // Arguments:
  681. //
  682. // Return Value:
  683. // TRUE : on success
  684. // FALSE : on failure
  685. // ***************************************************************************
  686. BOOL AddEventSource( HKEY hLogsKey, LPCWSTR pwszSource )
  687. {
  688. // local variables
  689. LONG lResult = 0;
  690. DWORD dwData = 0;
  691. DWORD dwLength = 0;
  692. DWORD dwDisposition = 0;
  693. HKEY hSourcesKey = NULL;
  694. LPWSTR pwszBuffer = NULL;
  695. // validate the inputs
  696. if ( hLogsKey == NULL || pwszSource == NULL )
  697. {
  698. SetLastError( ERROR_INVALID_PARAMETER );
  699. SaveLastError();
  700. return FALSE;
  701. }
  702. // set the name of the message file ( +2 == buffer )
  703. dwLength = StringLength( L"%SystemRoot%\\System32\\EventCreate.exe", 0 ) + 2;
  704. pwszBuffer = ( LPWSTR) AllocateMemory( dwLength * sizeof( WCHAR ) );
  705. if ( pwszBuffer == NULL )
  706. {
  707. // set the error and return
  708. SaveLastError();
  709. return FALSE;
  710. }
  711. // copy the required value into buffer
  712. StringCopy( pwszBuffer, L"%SystemRoot%\\System32\\EventCreate.exe", dwLength );
  713. // create the custom source
  714. lResult = RegCreateKeyEx( hLogsKey, pwszSource, 0, L"",
  715. REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hSourcesKey, &dwDisposition );
  716. if ( lResult != ERROR_SUCCESS )
  717. {
  718. SetLastError( lResult );
  719. SaveLastError();
  720. // free the allocated memory
  721. FreeMemory( &pwszBuffer );
  722. //return.
  723. return FALSE;
  724. }
  725. // add the name to the EventMessageFile subkey.
  726. lResult = RegSetValueEx( hSourcesKey, L"EventMessageFile",
  727. 0, REG_EXPAND_SZ, (LPBYTE) pwszBuffer, dwLength * sizeof( WCHAR ) );
  728. if ( lResult != ERROR_SUCCESS )
  729. {
  730. // save the error
  731. SetLastError( lResult );
  732. SaveLastError();
  733. // release the memories allocated till this point
  734. RegCloseKey( hSourcesKey );
  735. hSourcesKey = NULL;
  736. // free the allocated memory
  737. FreeMemory( &pwszBuffer );
  738. // return
  739. return FALSE;
  740. }
  741. // set the supported event types in the TypesSupported subkey.
  742. dwData = EVENTLOG_SUCCESS | EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
  743. lResult = RegSetValueEx( hSourcesKey,
  744. L"TypesSupported", 0, REG_DWORD, (LPBYTE) &dwData, sizeof( DWORD ) );
  745. if ( lResult != ERROR_SUCCESS )
  746. {
  747. // save the error
  748. SetLastError( lResult );
  749. SaveLastError();
  750. // release the memories allocated till this point
  751. RegCloseKey( hSourcesKey );
  752. hSourcesKey = NULL;
  753. // free the allocated memory
  754. FreeMemory( &pwszBuffer );
  755. // return
  756. return FALSE;
  757. }
  758. // mark this source as custom created source
  759. dwData = 1;
  760. lResult = RegSetValueEx( hSourcesKey,
  761. L"CustomSource", 0, REG_DWORD, (LPBYTE) &dwData, sizeof( DWORD ) );
  762. if ( lResult != ERROR_SUCCESS )
  763. {
  764. // save the error
  765. SetLastError( lResult );
  766. SaveLastError();
  767. // release the memories allocated till this point
  768. RegCloseKey( hSourcesKey );
  769. hSourcesKey = NULL;
  770. // free the allocated memory
  771. FreeMemory( &pwszBuffer );
  772. // return
  773. return FALSE;
  774. }
  775. // close the key
  776. RegCloseKey( hSourcesKey );
  777. // free the allocated memory
  778. FreeMemory( &pwszBuffer );
  779. // return success
  780. return TRUE;
  781. }
  782. BOOL ProcessOptions( LONG argc,
  783. LPCWSTR argv[],
  784. PTEVENTCREATE_PARAMS pParams, PBOOL pbNeedPwd )
  785. /*++
  786. Routine Description:
  787. This function parses the options specified at the command prompt
  788. Arguments:
  789. [ in ] argc - count of elements in argv
  790. [ in ] argv - command-line parameterd specified by the user
  791. [ out ] pbNeedPwd - sets to TRUE if -s exists without -p in 'argv'
  792. Return Value:
  793. TRUE - the parsing is successful
  794. FALSE - errors occured in parsing
  795. --*/
  796. {
  797. // local variables
  798. PTCMDPARSER2 pcmdOption = NULL;
  799. TCMDPARSER2 cmdOptions[ MAX_OPTIONS ];
  800. //
  801. // prepare the command options
  802. SecureZeroMemory( cmdOptions, sizeof( TCMDPARSER2 ) * MAX_OPTIONS );
  803. // -?
  804. pcmdOption = &cmdOptions[ OI_HELP ];
  805. StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
  806. pcmdOption->dwCount = 1;
  807. pcmdOption->dwFlags = CP2_USAGE;
  808. pcmdOption->dwType = CP_TYPE_BOOLEAN;
  809. pcmdOption->pValue = &pParams->bUsage;
  810. pcmdOption->pwszOptions = OPTION_HELP;
  811. // -s
  812. pcmdOption = &cmdOptions[ OI_SERVER ];
  813. StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
  814. pcmdOption->dwCount = 1;
  815. pcmdOption->dwFlags = CP2_ALLOCMEMORY | CP2_VALUE_TRIMINPUT | CP2_VALUE_NONULL;
  816. pcmdOption->dwType = CP_TYPE_TEXT;
  817. pcmdOption->pwszOptions = OPTION_SERVER;
  818. // -u
  819. pcmdOption = &cmdOptions[ OI_USERNAME ];
  820. StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
  821. pcmdOption->dwCount = 1;
  822. pcmdOption->dwFlags = CP2_ALLOCMEMORY | CP2_VALUE_TRIMINPUT | CP2_VALUE_NONULL;
  823. pcmdOption->dwType = CP_TYPE_TEXT;
  824. pcmdOption->pwszOptions = OPTION_USERNAME;
  825. // -p
  826. pcmdOption = &cmdOptions[ OI_PASSWORD ];
  827. StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
  828. pcmdOption->dwCount = 1;
  829. pcmdOption->dwFlags = CP2_ALLOCMEMORY | CP2_VALUE_OPTIONAL;
  830. pcmdOption->dwType = CP_TYPE_TEXT;
  831. pcmdOption->pwszOptions = OPTION_PASSWORD;
  832. // -log
  833. pcmdOption = &cmdOptions[ OI_LOG ];
  834. StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
  835. pcmdOption->dwCount = 1;
  836. pcmdOption->dwFlags = CP2_ALLOCMEMORY | CP2_VALUE_TRIMINPUT | CP2_VALUE_NONULL;
  837. pcmdOption->dwType = CP_TYPE_TEXT;
  838. pcmdOption->pwszOptions = OPTION_LOG;
  839. // -type
  840. pcmdOption = &cmdOptions[ OI_TYPE ];
  841. StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
  842. pcmdOption->dwCount = 1;
  843. pcmdOption->dwFlags = CP2_MODE_VALUES | CP2_ALLOCMEMORY |
  844. CP2_VALUE_TRIMINPUT | CP2_VALUE_NONULL | CP2_MANDATORY;
  845. pcmdOption->dwType = CP_TYPE_TEXT;
  846. pcmdOption->pwszValues = OVALUES_TYPE;
  847. pcmdOption->pwszOptions = OPTION_TYPE;
  848. // -source
  849. pcmdOption = &cmdOptions[ OI_SOURCE ];
  850. StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
  851. pcmdOption->dwCount = 1;
  852. pcmdOption->dwFlags = CP2_ALLOCMEMORY | CP2_VALUE_TRIMINPUT | CP2_VALUE_NONULL;
  853. pcmdOption->dwType = CP_TYPE_TEXT;
  854. pcmdOption->pwszOptions = OPTION_SOURCE;
  855. // -id
  856. pcmdOption = &cmdOptions[ OI_ID ];
  857. StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
  858. pcmdOption->dwCount = 1;
  859. pcmdOption->dwFlags = CP2_MANDATORY;
  860. pcmdOption->dwType = CP_TYPE_UNUMERIC;
  861. pcmdOption->pValue = &pParams->dwEventID;
  862. pcmdOption->pwszOptions = OPTION_ID;
  863. // -description
  864. pcmdOption = &cmdOptions[ OI_DESCRIPTION ];
  865. StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
  866. pcmdOption->dwCount = 1;
  867. pcmdOption->dwFlags = CP2_MANDATORY | CP2_ALLOCMEMORY | CP2_VALUE_TRIMINPUT | CP2_VALUE_NONULL;
  868. pcmdOption->dwType = CP_TYPE_TEXT;
  869. pcmdOption->pwszOptions = OPTION_DESCRIPTION;
  870. //
  871. // do the parsing
  872. if ( DoParseParam2( argc, argv, -1, MAX_OPTIONS, cmdOptions, 0 ) == FALSE )
  873. {
  874. return FALSE; // invalid syntax
  875. }
  876. //
  877. // now, check the mutually exclusive options
  878. // check the usage option
  879. if ( pParams->bUsage == TRUE )
  880. {
  881. if ( argc > 2 )
  882. {
  883. // no other options are accepted along with -? option
  884. SetLastError( (DWORD) MK_E_SYNTAX );
  885. SetReason( ERROR_INVALID_USAGE_REQUEST );
  886. return FALSE;
  887. }
  888. else
  889. {
  890. // no need of furthur checking of the values
  891. return TRUE;
  892. }
  893. }
  894. // validate the range of the event id specified
  895. if ( pParams->dwEventID < MSG_EVENTID_START ||
  896. pParams->dwEventID >= MSG_EVENTID_END )
  897. {
  898. SetReason2( 2, ERROR_ID_OUTOFRANGE, MSG_EVENTID_START, MSG_EVENTID_END - 1 );
  899. SetLastError( (DWORD) MK_E_SYNTAX );
  900. return FALSE;
  901. }
  902. // get the buffer pointers allocated by command line parser
  903. pParams->pwszType = cmdOptions[ OI_TYPE ].pValue;
  904. pParams->pwszLogName = cmdOptions[ OI_LOG ].pValue;
  905. pParams->pwszSource = cmdOptions[ OI_SOURCE ].pValue;
  906. pParams->pwszServer = cmdOptions[ OI_SERVER ].pValue;
  907. pParams->pwszUserName = cmdOptions[ OI_USERNAME ].pValue;
  908. pParams->pwszPassword = cmdOptions[ OI_PASSWORD ].pValue;
  909. pParams->pwszDescription = cmdOptions[ OI_DESCRIPTION ].pValue;
  910. // "-u" should not be specified without "-s"
  911. if ( pParams->pwszUserName != NULL && pParams->pwszServer == NULL )
  912. {
  913. // invalid syntax
  914. SetLastError( (DWORD) MK_E_SYNTAX );
  915. SetReason( ERROR_USERNAME_BUT_NOMACHINE );
  916. return FALSE; // indicate failure
  917. }
  918. // "-p" should not be specified without "-u"
  919. if ( pParams->pwszPassword != NULL && pParams->pwszUserName == NULL )
  920. {
  921. // invalid syntax
  922. SetReason( ERROR_PASSWORD_BUT_NOUSERNAME );
  923. return FALSE; // indicate failure
  924. }
  925. // check the remote connectivity information
  926. if ( pParams->pwszServer != NULL )
  927. {
  928. //
  929. // if -u is not specified, we need to allocate memory
  930. // in order to be able to retrive the current user name
  931. //
  932. // case 1: -p is not at all specified
  933. // as the value for this switch is optional, we have to rely
  934. // on the dwActuals to determine whether the switch is specified or not
  935. // in this case utility needs to try to connect first and if it fails
  936. // then prompt for the password -- in fact, we need not check for this
  937. // condition explicitly except for noting that we need to prompt for the
  938. // password
  939. //
  940. // case 2: -p is specified
  941. // but we need to check whether the value is specified or not
  942. // in this case user wants the utility to prompt for the password
  943. // before trying to connect
  944. //
  945. // case 3: -p * is specified
  946. // user name
  947. if ( pParams->pwszUserName == NULL )
  948. {
  949. pParams->dwUserNameLength = MAX_STRING_LENGTH;
  950. pParams->pwszUserName = AllocateMemory( MAX_STRING_LENGTH * sizeof( WCHAR ) );
  951. if ( pParams->pwszUserName == NULL )
  952. {
  953. SaveLastError();
  954. return FALSE;
  955. }
  956. }
  957. else
  958. {
  959. pParams->dwUserNameLength = StringLength( pParams->pwszUserName, 0 ) + 1;
  960. }
  961. // password
  962. if ( pParams->pwszPassword == NULL )
  963. {
  964. *pbNeedPwd = TRUE;
  965. pParams->dwPasswordLength = MAX_STRING_LENGTH;
  966. pParams->pwszPassword = AllocateMemory( MAX_STRING_LENGTH * sizeof( WCHAR ) );
  967. if ( pParams->pwszPassword == NULL )
  968. {
  969. SaveLastError();
  970. return FALSE;
  971. }
  972. }
  973. // case 1
  974. if ( cmdOptions[ OI_PASSWORD ].dwActuals == 0 )
  975. {
  976. // we need not do anything special here
  977. }
  978. // case 2
  979. else if ( cmdOptions[ OI_PASSWORD ].pValue == NULL )
  980. {
  981. StringCopy( pParams->pwszPassword, L"*", pParams->dwPasswordLength );
  982. }
  983. // case 3
  984. else if ( StringCompareEx( pParams->pwszPassword, L"*", TRUE, 0 ) == 0 )
  985. {
  986. if ( ReallocateMemory( &pParams->pwszPassword,
  987. MAX_STRING_LENGTH * sizeof( WCHAR ) ) == FALSE )
  988. {
  989. SaveLastError();
  990. return FALSE;
  991. }
  992. // ...
  993. *pbNeedPwd = TRUE;
  994. pParams->dwPasswordLength = MAX_STRING_LENGTH;
  995. }
  996. }
  997. // either -source (or) -log must be specified ( both can also be specified )
  998. if ( pParams->pwszSource == NULL && pParams->pwszLogName == NULL )
  999. {
  1000. // if log name and application were not specified, we will set to defaults
  1001. pParams->pwszLogName = g_wszDefaultLog;
  1002. pParams->pwszSource = g_wszDefaultSource;
  1003. }
  1004. // if log is "application" and source is not specified, even then we
  1005. // will default the source to "EventCreate"
  1006. else if ( pParams->pwszSource == NULL &&
  1007. pParams->pwszLogName != NULL &&
  1008. StringCompareEx( pParams->pwszLogName, g_wszDefaultLog, TRUE, 0 ) == 0 )
  1009. {
  1010. pParams->pwszSource = g_wszDefaultSource;
  1011. }
  1012. // block the user to create events in security log
  1013. if ( pParams->pwszLogName != NULL &&
  1014. StringCompare( pParams->pwszLogName, L"security", TRUE, 0 ) == 0 )
  1015. {
  1016. SetReason( ERROR_LOG_CANNOT_BE_SECURITY );
  1017. return FALSE;
  1018. }
  1019. // determine the actual event type
  1020. if ( StringCompareEx( pParams->pwszType, LOGTYPE_ERROR, TRUE, 0 ) == 0 )
  1021. {
  1022. pParams->wEventType = EVENTLOG_ERROR_TYPE;
  1023. }
  1024. else if ( StringCompareEx( pParams->pwszType, LOGTYPE_SUCCESS, TRUE, 0 ) == 0 )
  1025. {
  1026. pParams->wEventType = EVENTLOG_SUCCESS;
  1027. }
  1028. else if ( StringCompareEx( pParams->pwszType, LOGTYPE_WARNING, TRUE, 0 ) == 0 )
  1029. {
  1030. pParams->wEventType = EVENTLOG_WARNING_TYPE;
  1031. }
  1032. else if ( StringCompareEx( pParams->pwszType, LOGTYPE_INFORMATION, TRUE, 0 ) == 0 )
  1033. {
  1034. pParams->wEventType = EVENTLOG_INFORMATION_TYPE;
  1035. }
  1036. // command-line parsing is successfull
  1037. return TRUE;
  1038. }
  1039. BOOL
  1040. Usage()
  1041. /*++
  1042. Routine Description:
  1043. Arguments:
  1044. Return Value:
  1045. --*/
  1046. {
  1047. // local variables
  1048. DWORD dw = 0;
  1049. // start displaying the usage
  1050. for( dw = ID_USAGE_START; dw <= ID_USAGE_END; dw++ )
  1051. {
  1052. ShowMessage( stdout, GetResString( dw ) );
  1053. }
  1054. // return
  1055. return TRUE;
  1056. }
  1057. BOOL
  1058. UnInitializeGlobals( PTEVENTCREATE_PARAMS pParams )
  1059. /*++
  1060. Routine Description:
  1061. Arguments:
  1062. Return Value:
  1063. --*/
  1064. {
  1065. // close the connection -- if needed
  1066. if ( pParams->bCloseConnection == TRUE )
  1067. {
  1068. CloseConnection( pParams->pwszServer );
  1069. }
  1070. //
  1071. // NOTE: FreeMemory will clear the contents of the
  1072. // password buffer -- since it will be duplicated
  1073. //
  1074. // release the memory allocated
  1075. FreeMemory( &pParams->pwszServer );
  1076. FreeMemory( &pParams->pwszUserName );
  1077. FreeMemory( &pParams->pwszPassword );
  1078. FreeMemory( &pParams->pwszType );
  1079. FreeMemory( &pParams->pwszDescription );
  1080. //
  1081. // check the pointers -- if it is not pointing to constant pointer
  1082. // then only release it
  1083. //
  1084. if ( pParams->pwszLogName != g_wszDefaultLog )
  1085. {
  1086. FreeMemory( &pParams->pwszLogName );
  1087. }
  1088. if ( pParams->pwszSource != g_wszDefaultSource )
  1089. {
  1090. FreeMemory( &pParams->pwszSource );
  1091. }
  1092. return TRUE;
  1093. }