Source code of Windows XP (NT5)
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.

936 lines
41 KiB

  1. /*======================================================================================//
  2. | Windows 2000 Process Control //
  3. | //
  4. |Copyright (c) 1998, 1999 Sequent Computer Systems, Incorporated. All rights reserved //
  5. | //
  6. |File Name: ProcConLib.cpp //
  7. | //
  8. |Description: This implements the ProcCon client side API in a static library //
  9. | //
  10. |Created: Jarl McDonald 08-98 //
  11. | //
  12. |Rev History: //
  13. | //
  14. |=======================================================================================*/
  15. #include <windows.h>
  16. #include <stddef.h>
  17. #include <stdlib.h>
  18. #include <tchar.h>
  19. #include <time.h>
  20. #include "ProcConAPI.h"
  21. #include "ProcConClnt.h"
  22. #define ENTRY_COUNT(x) (sizeof(x) / sizeof(x[0]))
  23. typedef struct _PCConnection {
  24. TCHAR name[MAX_PATH];
  25. HANDLE handle;
  26. PCUINT32 connCount;
  27. time_t connTime;
  28. PCUINT32 flags;
  29. PCUINT32 lastError;
  30. PCINT32 reqSeq;
  31. char *buffer;
  32. PCINT32 bufSize;
  33. DWORD timeout;
  34. OVERLAPPED overlap;
  35. } PCConnection;
  36. typedef enum _PCConnFlags {
  37. PCAPIFLAG_FREEBUFFER = 0x01000000,
  38. };
  39. const PCINT32 SIGNATURE = 0xd06eface;
  40. const TCHAR *PIPENAME = TEXT("\\pipe\\ProcConPip");
  41. static PCConnection connTbl[128];
  42. static PCid nextId = 0;
  43. //======================================================================================//
  44. // Library internal functions
  45. //======================================================================================//
  46. static PCINT32 PCMaxItemCount( PCid target,
  47. PCINT32 bufSize,
  48. PCINT32 itemSize )
  49. {
  50. PCINT32 maxUsrBuf = bufSize / itemSize;
  51. PCINT32 maxIOBuf = (connTbl[target].bufSize - offsetof(PCResponse, rspData)) / itemSize;
  52. return min(maxUsrBuf, maxIOBuf);
  53. }
  54. static BOOL PCIsValidPCId( PCid target )
  55. {
  56. if ( target <= 0 || target >= ENTRY_COUNT(connTbl) )
  57. connTbl[0].lastError = PCERROR_INVALID_PCID;
  58. else if ( !connTbl[target].handle )
  59. connTbl[target].lastError = PCERROR_INVALID_PCID;
  60. else return TRUE;
  61. return FALSE;
  62. }
  63. static void PCBuildReq( PCid target,
  64. BYTE op,
  65. BYTE itemType,
  66. void *pItem = NULL,
  67. PCINT16 itemSize = 0,
  68. PCINT32 maxReply = 0,
  69. PCINT64 index = 0,
  70. PCINT32 count = 1,
  71. PCINT32 first = 0,
  72. PCINT32 updateCtr = 0 )
  73. {
  74. PCRequest *req = (PCRequest *) connTbl[target].buffer;
  75. connTbl[target].lastError = PCERROR_SUCCESS;
  76. memset( req, 0, sizeof( *req ) );
  77. req->reqSignature = SIGNATURE; // sanity check signature
  78. req->reqSeq = ++connTbl[target].reqSeq; // requestor sequence number
  79. req->reqOp = op; // requested operation: get
  80. req->reqType = itemType; // requested data type: name rule
  81. req->reqVersion = 1; // expected data version code
  82. req->reqUpdCtr = updateCtr; // requestor's update counter from get
  83. req->reqIndex = index; // requestor's insert point, etc.
  84. req->reqCount = count; // requestor's returned data item max count
  85. req->reqFirst = first; // requestor's first index to retrieve
  86. req->maxReply = min( (PCUINT32) maxReply,
  87. (PCUINT32) connTbl[target].bufSize - offsetof(PCResponse, rspData) );
  88. req->reqDataLen = itemSize; // data length that follows.
  89. if ( pItem ) memcpy( req->reqData, pItem, itemSize );
  90. }
  91. static BOOL PCReopen( PCid id )
  92. {
  93. ++connTbl[id].connCount;
  94. connTbl[id].connTime = time( NULL );
  95. connTbl[id].handle = INVALID_HANDLE_VALUE;
  96. // Connect to desired server and pipe...
  97. if ( WaitNamedPipe( connTbl[id].name, NMPWAIT_USE_DEFAULT_WAIT ) )
  98. connTbl[id].handle = CreateFile( connTbl[id].name, GENERIC_READ + GENERIC_WRITE, 0,
  99. NULL, OPEN_EXISTING,
  100. SECURITY_SQOS_PRESENT + SECURITY_IMPERSONATION + FILE_FLAG_OVERLAPPED,
  101. NULL );
  102. // Update table entry...
  103. connTbl[id].lastError = connTbl[id].handle == INVALID_HANDLE_VALUE? GetLastError() : PCERROR_SUCCESS;
  104. // return success or fail indication...
  105. return connTbl[id].lastError == PCERROR_SUCCESS;
  106. }
  107. static BOOL PCRetryCode( PCid id )
  108. {
  109. static PCUINT32 retryCodes[] = { ERROR_BAD_PIPE, ERROR_PIPE_BUSY, ERROR_NO_DATA,
  110. ERROR_PIPE_NOT_CONNECTED, ERROR_BROKEN_PIPE, ERROR_SEM_TIMEOUT,
  111. ERROR_NETNAME_DELETED, ERROR_INVALID_HANDLE };
  112. for ( PCUINT32 i = 0; i < ENTRY_COUNT(retryCodes); ++i )
  113. if ( connTbl[id].lastError == retryCodes[i] ) return TRUE;
  114. return FALSE;
  115. }
  116. static void PCSetReqFlag( PCid target, PCINT32 flag )
  117. {
  118. ((PCRequest *) connTbl[target].buffer)->reqFlags |= flag;
  119. }
  120. static BOOL PCTestResponse( PCid target,
  121. PCUINT32 bytesActual )
  122. {
  123. PCResponse *rsp = (PCResponse *) connTbl[target].buffer;
  124. PCUINT32 hdrBytesExpected = sizeof(PCResponse) - sizeof(rsp->rspData);
  125. if ( bytesActual < hdrBytesExpected ) {
  126. connTbl[target].lastError = PCERROR_INVALID_RESPONSE_LENGTH;
  127. return FALSE;
  128. }
  129. if ( rsp->rspReqSignature != SIGNATURE || rsp->rspReqSeq != connTbl[target].reqSeq ) {
  130. connTbl[target].lastError = PCERROR_INVALID_RESPONSE;
  131. return FALSE;
  132. }
  133. PCUINT32 dataBytesReceived = rsp->rspDataItemCount * rsp->rspDataItemLen;
  134. if ( bytesActual < hdrBytesExpected + dataBytesReceived ) {
  135. connTbl[target].lastError = PCERROR_INVALID_RESPONSE_LENGTH;
  136. return FALSE;
  137. }
  138. if ( rsp->rspResult != PCRESULT_SUCCESS ) {
  139. connTbl[target].lastError = rsp->rspError;
  140. return FALSE;
  141. }
  142. connTbl[target].lastError = PCERROR_SUCCESS;
  143. return TRUE;
  144. }
  145. static PCINT32 PCCopyData( PCid target,
  146. void *pData,
  147. PCINT32 maxItemsRequested,
  148. PCUINT32 maxLen,
  149. PCINT32 *nUpdateCtr = NULL )
  150. {
  151. PCResponse *rsp = (PCResponse *) connTbl[target].buffer;
  152. if ( rsp->rspFlags & PCRSPFLAG_MOREDATA ) connTbl[target].lastError = PCERROR_MORE_DATA;
  153. if ( nUpdateCtr ) *nUpdateCtr = rsp->rspUpdCtr;
  154. PCUINT32 items = min( rsp->rspDataItemCount, maxItemsRequested );
  155. PCUINT32 copyLen = items * rsp->rspDataItemLen;
  156. if ( copyLen > maxLen ) {
  157. connTbl[target].lastError = PCERROR_TRUNCATED;
  158. items = maxLen / rsp->rspDataItemLen;
  159. copyLen = items * rsp->rspDataItemLen;
  160. }
  161. memcpy( pData, rsp->rspData, copyLen );
  162. return items;
  163. }
  164. static BOOL PCReadRsp( PCid target )
  165. {
  166. BOOL test;
  167. do {
  168. PCULONG32 bytesRead;
  169. ResetEvent( connTbl[target].overlap.hEvent );
  170. PCULONG32 rc = ReadFile( connTbl[target].handle,
  171. connTbl[target].buffer, connTbl[target].bufSize,
  172. &bytesRead, &connTbl[target].overlap );
  173. if ( !rc && GetLastError() != ERROR_IO_PENDING ) {
  174. connTbl[target].lastError = GetLastError();
  175. return FALSE;
  176. }
  177. if ( WAIT_TIMEOUT == WaitForSingleObject( connTbl[target].overlap.hEvent, connTbl[target].timeout ) ) {
  178. CancelIo( connTbl[target].handle );
  179. connTbl[target].lastError = PCERROR_REQUEST_TIMED_OUT;
  180. return FALSE;
  181. }
  182. else if ( !GetOverlappedResult( connTbl[target].handle, &connTbl[target].overlap, &bytesRead, FALSE ) ) {
  183. connTbl[target].lastError = GetLastError();
  184. return FALSE;
  185. }
  186. test = PCTestResponse( target, bytesRead );
  187. } while ( !test && PCGetLastError( target ) == PCERROR_INVALID_RESPONSE );
  188. return test;
  189. }
  190. static BOOL PCSendReceive( PCid target )
  191. {
  192. PCRequest *req = (PCRequest *) connTbl[target].buffer;
  193. PCULONG32 bytesActual, bytesToWrite = sizeof(PCRequest) - sizeof(req->reqData) + req->reqDataLen;
  194. ResetEvent( connTbl[target].overlap.hEvent );
  195. for ( int retryCt = 0; retryCt < PC_MAX_RETRIES + 1; ++retryCt ) {
  196. PCULONG32 rc = WriteFile( connTbl[target].handle, req, bytesToWrite, &bytesActual, &connTbl[target].overlap );
  197. if ( rc || GetLastError() == ERROR_IO_PENDING ) break;
  198. else {
  199. connTbl[target].lastError = GetLastError();
  200. if ( PCRetryCode( target ) ) Sleep( rand() * 300 / RAND_MAX );
  201. else return FALSE;
  202. PCReopen( target );
  203. }
  204. }
  205. if ( WAIT_TIMEOUT == WaitForSingleObject( connTbl[target].overlap.hEvent, connTbl[target].timeout ) ) {
  206. CancelIo( connTbl[target].handle );
  207. connTbl[target].lastError = PCERROR_REQUEST_TIMED_OUT;
  208. return FALSE;
  209. }
  210. else if ( !GetOverlappedResult( connTbl[target].handle, &connTbl[target].overlap, &bytesActual, FALSE ) ) {
  211. connTbl[target].lastError = GetLastError();
  212. return FALSE;
  213. }
  214. if ( retryCt >= PC_MAX_RETRIES + 1 ) return FALSE;
  215. if ( bytesToWrite != bytesActual ) {
  216. connTbl[target].lastError = PCERROR_IO_INCOMPLETE;
  217. return FALSE;
  218. }
  219. return PCReadRsp( target );
  220. }
  221. //======================================================================================//
  222. // PCOpen -- establish connection to PC on named machine.
  223. // Returns: PCid to use with future PC calls or 0 on error (use PCGetLastError).
  224. // Arguments: 0) pointer to target computer name or NULL to use local machine,
  225. // 1) buffer to be used in server communication or NULL (library allocates).
  226. // 2) size of buffer supplied or to be allocated in bytes.
  227. //======================================================================================//
  228. PCid PCOpen( const TCHAR *targetComputer, char *buffer, PCUINT32 bufSize )
  229. {
  230. if ( bufSize < PC_MIN_BUF_SIZE || bufSize > PC_MAX_BUF_SIZE ) {
  231. connTbl[0].lastError = PCERROR_INVALID_PARAMETER;
  232. return 0;
  233. }
  234. TCHAR pipe[MAX_PATH];
  235. _tcscpy( pipe, TEXT("\\\\") );
  236. _tcscat( pipe, targetComputer? targetComputer : TEXT(".") );
  237. _tcscat( pipe, PIPENAME );
  238. // Connect to desired server and pipe...
  239. if ( WaitNamedPipe( pipe, NMPWAIT_USE_DEFAULT_WAIT ) ) {
  240. HANDLE hPipe = CreateFile( pipe, GENERIC_READ + GENERIC_WRITE, 0,
  241. NULL, OPEN_EXISTING,
  242. SECURITY_SQOS_PRESENT + SECURITY_IMPERSONATION + FILE_FLAG_OVERLAPPED,
  243. NULL );
  244. // Map result to local handle table and return index...
  245. if ( hPipe != INVALID_HANDLE_VALUE ) {
  246. if ( ++nextId >= ENTRY_COUNT(connTbl) ) nextId = 1;
  247. for ( int i = nextId, ctr = 1;
  248. ctr++ < ENTRY_COUNT(connTbl) && connTbl[i].handle;
  249. i = i >= ENTRY_COUNT(connTbl)? 1 : i + 1 ) ;
  250. if ( ctr >= ENTRY_COUNT(connTbl) ) {
  251. connTbl[0].lastError = PCERROR_TOO_MANY_CONNECTIONS;
  252. CloseHandle( hPipe );
  253. return 0;
  254. }
  255. if ( !buffer ) {
  256. buffer = new char[bufSize];
  257. if ( buffer ) connTbl[i].flags |= PCAPIFLAG_FREEBUFFER;
  258. else {
  259. connTbl[0].lastError = ERROR_NOT_ENOUGH_MEMORY;
  260. CloseHandle( hPipe );
  261. return 0;
  262. }
  263. }
  264. _tcscpy( connTbl[i].name, pipe );
  265. connTbl[i].handle = hPipe;
  266. connTbl[i].connCount = 1;
  267. connTbl[i].connTime = time( NULL );
  268. connTbl[i].lastError = PCERROR_SUCCESS;
  269. connTbl[i].buffer = buffer;
  270. connTbl[i].bufSize = bufSize;
  271. connTbl[i].timeout = 5000;
  272. memset( &connTbl[i].overlap, 0, sizeof(connTbl[i].overlap) );
  273. connTbl[i].overlap.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
  274. return i;
  275. }
  276. }
  277. DWORD lErr = GetLastError();
  278. connTbl[0].lastError = (lErr == ERROR_FILE_NOT_FOUND)? PCERROR_SERVICE_NOT_RUNNING : lErr;
  279. return 0;
  280. }
  281. //======================================================================================//
  282. // PCClose -- break connection to PC on previously connected machine.
  283. // Returns: TRUE on success.
  284. // FALSE on failure, use PCGetLastError.
  285. // Arguments: 0) PCid from PCOpen,
  286. //======================================================================================//
  287. BOOL PCClose( PCid target )
  288. {
  289. BOOL rc = PCIsValidPCId( target );
  290. if ( rc ) {
  291. if ( !CloseHandle( connTbl[target].handle ) ) {
  292. connTbl[target].lastError = GetLastError();
  293. rc = FALSE;
  294. }
  295. if ( connTbl[target].flags & PCAPIFLAG_FREEBUFFER ) {
  296. delete [] connTbl[target].buffer;
  297. }
  298. connTbl[target].handle = connTbl[target].buffer = NULL;
  299. connTbl[target].flags = connTbl[target].bufSize = 0;
  300. }
  301. return rc;
  302. }
  303. //======================================================================================//
  304. // PCGetLastError -- return last error reported for a target
  305. // Returns: last PC API error for this client.
  306. // Arguments: 0) PCid from PCOpen,
  307. //======================================================================================//
  308. PCULONG32 PCGetLastError( PCid target )
  309. {
  310. if ( target >= 0 && target < ENTRY_COUNT(connTbl) )
  311. return connTbl[target].lastError;
  312. else
  313. return PCERROR_INVALID_PCID;
  314. }
  315. //======================================================================================//
  316. // PCGetServiceInfo -- get ProcCon Service indentification and parameters.
  317. // Returns: TRUE on success.
  318. // FALSE on failure, use PCGetLastError.
  319. // Arguments: 0) PCid from PCOpen,
  320. // 1) pointer to area to receive system information,
  321. // 2) size of this area in bytes,
  322. //======================================================================================//
  323. BOOL PCGetServiceInfo( PCid target, PCSystemInfo *sysInfo, PCINT32 nByteCount )
  324. {
  325. if ( !PCIsValidPCId( target ) ) return FALSE;
  326. // Build request...
  327. PCBuildReq( target, PCOP_GET, PCTYPE_SERVERINFO );
  328. // Send request, receive response and verify success...
  329. if ( !PCSendReceive( target ) ) return FALSE;
  330. // Pass appropriate data back to caller...
  331. PCCopyData( target, sysInfo, 1, nByteCount );
  332. return TRUE;
  333. }
  334. //======================================================================================//
  335. // PCControlFunction -- various ProcCon control functions to support restore, etc.
  336. // Returns: TRUE on success.
  337. // FALSE on failure, use PCGetLastError.
  338. // Arguments: 0) PCid from PCOpen,
  339. // 1) control flags to describe desired control functions,
  340. // 2) [optional] data that modifies control function.
  341. //======================================================================================//
  342. BOOL PCControlFunction( PCid target, PCINT32 ctlFlags, PCINT32 ctlData )
  343. {
  344. if ( !PCIsValidPCId( target ) ) return FALSE;
  345. // Build request...
  346. PCBuildReq( target, PCOP_CTL, PCTYPE_CONTROL, NULL, 0, 0, ctlFlags, ctlData );
  347. // Send request, receive response and pass back result...
  348. return PCSendReceive( target );
  349. }
  350. //======================================================================================//
  351. // PCSetServiceParms -- set ProcCon Service parameters.
  352. // Returns: TRUE on success.
  353. // FALSE on failure, use PCGetLastError.
  354. // Arguments: 0) PCid from PCOpen,
  355. // 1) pointer to area containing new system parameters,
  356. // 2) size of this area in bytes,
  357. //======================================================================================//
  358. BOOL PCSetServiceParms( PCid target, PCSystemParms *sysParms, PCINT32 nByteCount )
  359. {
  360. if ( !PCIsValidPCId( target ) ) return FALSE;
  361. // Apply timeout locally...
  362. // We apply our value right away so that it covers this call...
  363. // If out of range, reject it and skip calling the server.
  364. if ( sysParms->timeoutValueMs < PC_MIN_TIMEOUT ||
  365. sysParms->timeoutValueMs > PC_MAX_TIMEOUT ) {
  366. connTbl[target].lastError = PCERROR_INVALID_PARAMETER;
  367. return FALSE;
  368. }
  369. else
  370. connTbl[target].timeout = sysParms->timeoutValueMs;
  371. // Build request...
  372. PCBuildReq( target, PCOP_REP, PCTYPE_SERVERPARMS, sysParms,
  373. sizeof(PCSystemParms), nByteCount );
  374. // Send request, receive response and pass back result...
  375. BOOL rc = PCSendReceive( target );
  376. return rc;
  377. }
  378. //======================================================================================//
  379. // PCKillProcess -- kill the specified process
  380. // Returns: TRUE on success.
  381. // FALSE on failure, use PCGetLastError.
  382. // Arguments: 0) PCid from PCOpen,
  383. // 1) Pid of the process to kill from PCGetProcList statistics,
  384. // 2) Create time of the process to kill from PCGetProcList statistics.
  385. //======================================================================================//
  386. BOOL PCKillProcess( PCid target, PID_VALUE processPid, TIME_VALUE createTime )
  387. {
  388. if ( !PCIsValidPCId( target ) ) return FALSE;
  389. // Build request...
  390. PCBuildReq( target, PCOP_KILL, PCTYPE_PROCLIST, &createTime, sizeof(createTime), 0, processPid );
  391. // Send request, receive response and pass back result...
  392. return PCSendReceive( target );
  393. }
  394. //======================================================================================//
  395. // PCKillJob -- kill the specified job
  396. // Returns: TRUE on success.
  397. // FALSE on failure, use PCGetLastError.
  398. // Arguments: 0) PCid from PCOpen,
  399. // 1) Name of the job to kill.
  400. //======================================================================================//
  401. BOOL PCKillJob( PCid target, JOB_NAME jobName )
  402. {
  403. if ( !PCIsValidPCId( target ) ) return FALSE;
  404. // Build request...
  405. PCBuildReq( target, PCOP_KILL, PCTYPE_JOBLIST, jobName, sizeof(JOB_NAME) );
  406. // Send request, receive response and pass back result...
  407. return PCSendReceive( target );
  408. }
  409. //======================================================================================//
  410. // PCGetNameRules -- get fixed-format table containing name rules, one entry per rule.
  411. // Returns: 1 or greater to indicate the number of items in the response (may be incomplete).
  412. // -1 on failure, use PCGetLastError.
  413. // Arguments: 0) PCid from PCOpen,
  414. // 1) pointer to table to receive name rule list,
  415. // 2) size of this table in bytes,
  416. // 3) [optional, default is 0] index of first entry to return (0-relative),
  417. // 4) [optional] location to store update counter to be supplied on update.
  418. // Notes: If PCGetLastError returns PCERROR_MORE_DATA, there is more data to retrieve.
  419. // Name rule order is significant: rules are executed from top to bottom.
  420. //======================================================================================//
  421. PCINT32 PCGetNameRules( PCid target, PCNameRule *pRuleList, PCINT32 nByteCount,
  422. PCINT32 nFirst, PCINT32 *nUpdateCtr )
  423. {
  424. if ( !PCIsValidPCId( target ) ) return -1;
  425. // Build request...
  426. PCINT32 maxItemsRequested = PCMaxItemCount( target, nByteCount, sizeof(PCNameRule) );
  427. PCBuildReq( target, PCOP_GET, PCTYPE_NAMERULE,
  428. pRuleList, sizeof(PCNameRule), nByteCount,
  429. 0, maxItemsRequested, nFirst );
  430. // Send request, receive response and verify success...
  431. if ( !PCSendReceive( target ) ) return -1;
  432. // Pass appropriate data back to caller...
  433. return PCCopyData( target, pRuleList, maxItemsRequested, nByteCount, nUpdateCtr );
  434. }
  435. //======================================================================================//
  436. // PCGetProcSummary -- get fixed-format table summarizing all defined processes.
  437. // Returns: 0 or greater to indicate the number of items in the response (may be incomplete).
  438. // -1 on failure, use PCGetLastError.
  439. // Arguments: 0) PCid from PCOpen,
  440. // 1) pointer to table to receive rule summary list, first entry indicates start point,
  441. // 2) size of this table in bytes.
  442. // 3) a set of flags used to further specify or limit list operation.
  443. // Notes: If PCGetLastError returns PCERROR_MORE_DATA, there is more data to retrieve.
  444. // List entries are in alphabetic order by process name.
  445. //======================================================================================//
  446. PCINT32 PCGetProcSummary( PCid target, PCProcSummary *pProcList, PCINT32 nByteCount, PCUINT32 listFlags )
  447. {
  448. if ( !PCIsValidPCId( target ) ) return -1;
  449. // Build request...
  450. PCINT32 maxItemsRequested = PCMaxItemCount( target, nByteCount, sizeof(PCProcSummary) );
  451. PCBuildReq( target, PCOP_GET, PCTYPE_PROCSUMMARY,
  452. pProcList, sizeof(PCProcSummary), nByteCount, listFlags, maxItemsRequested );
  453. // Send request, receive response and verify success...
  454. if ( !PCSendReceive( target ) ) return -1;
  455. // Pass appropriate data back to caller...
  456. return PCCopyData( target, pProcList, maxItemsRequested, nByteCount );
  457. }
  458. //======================================================================================//
  459. // PCGetJobSummary -- get fixed-format table summarizing all defined jobs.
  460. // Returns: 0 or greater to indicate the number of items in the response (may be incomplete).
  461. // -1 on failure, use PCGetLastError.
  462. // Arguments: 0) PCid from PCOpen,
  463. // 1) pointer to table to receive rule summary list, first entry indicates start point,
  464. // 2) size of this table in bytes.
  465. // 3) a set of flags used to further specify or limit list operation.
  466. // Notes: If PCGetLastError returns PCERROR_MORE_DATA, there is more data to retrieve.
  467. // List entries are in alphabetic order by job name.
  468. //======================================================================================//
  469. PCINT32 PCGetJobSummary( PCid target, PCJobSummary *pJobList, PCINT32 nByteCount, PCUINT32 listFlags )
  470. {
  471. if ( !PCIsValidPCId( target ) ) return -1;
  472. // Build request...
  473. PCINT32 maxItemsRequested = PCMaxItemCount( target, nByteCount, sizeof(PCJobSummary) );
  474. PCBuildReq( target, PCOP_GET, PCTYPE_JOBSUMMARY,
  475. pJobList, sizeof(PCJobSummary), nByteCount, listFlags, maxItemsRequested );
  476. // Send request, receive response and verify success...
  477. if ( !PCSendReceive( target ) ) return -1;
  478. // Pass appropriate data back to caller...
  479. return PCCopyData( target, pJobList, maxItemsRequested, nByteCount );
  480. }
  481. //======================================================================================//
  482. // PCGetJobList -- get list of all defined jobs, both running and not.
  483. // Returns: 0 or greater to indicate the number of items in the response (may be incomplete).
  484. // -1 on failure, use PCGetLastError.
  485. // Arguments: 0) PCid from PCOpen,
  486. // 1) pointer to structure to receive job list,
  487. // 2) size of this structure in bytes.
  488. // 3) a TRUE/FALSE flag indicating if only running jobs should be included.
  489. // Notes: If PCGetLastError returns PCERROR_MORE_DATA, there is more data to retrieve.
  490. // List entries are in alphabetic order by job name.
  491. //======================================================================================//
  492. PCINT32 PCGetJobList( PCid target, PCJobListItem *pJobList, PCINT32 nByteCount, PCUINT32 listFlags )
  493. {
  494. if ( !PCIsValidPCId( target ) ) return -1;
  495. // Build request...
  496. PCINT32 maxItemsRequested = PCMaxItemCount( target, nByteCount, sizeof(PCJobListItem) );
  497. PCBuildReq( target, PCOP_GET, PCTYPE_JOBLIST,
  498. pJobList, sizeof(PCJobListItem), nByteCount, listFlags, maxItemsRequested );
  499. // Send request, receive response and verify success...
  500. if ( !PCSendReceive( target ) ) return -1;
  501. // Pass appropriate data back to caller...
  502. return PCCopyData( target, pJobList, maxItemsRequested, nByteCount );
  503. }
  504. //======================================================================================//
  505. // PCGetProcList -- get list of all defined process names, both running and not.
  506. // Returns: 0 or greater to indicate the number of items in the response (may be incomplete).
  507. // -1 on failure, use PCGetLastError.
  508. // Arguments: 0) PCid from PCOpen,
  509. // 1) pointer to structure to receive process list,
  510. // 2) size of this structure in bytes.
  511. // 3) a TRUE/FALSE flag indicating if only running jobs should be included.
  512. // Notes: If PCGetLastError returns PCERROR_MORE_DATA, there is more data to retrieve.
  513. // List entries are in alphabetic order by process name.
  514. //======================================================================================//
  515. PCINT32 PCGetProcList( PCid target, PCProcListItem *pProcList, PCINT32 nByteCount, PCUINT32 listFlags )
  516. {
  517. if ( !PCIsValidPCId( target ) ) return -1;
  518. // Build request...
  519. PCINT32 maxItemsRequested = PCMaxItemCount( target, nByteCount, sizeof(PCProcListItem) );
  520. PCBuildReq( target, PCOP_GET, PCTYPE_PROCLIST,
  521. pProcList, sizeof(PCProcListItem), nByteCount, listFlags, maxItemsRequested );
  522. // Send request, receive response and verify success...
  523. if ( !PCSendReceive( target ) ) return -1;
  524. // Pass appropriate data back to caller...
  525. return PCCopyData( target, pProcList, maxItemsRequested, nByteCount );
  526. }
  527. //======================================================================================//
  528. // PCGetProcDetail -- get full management and descriptive data associated with a process name.
  529. // Returns: TRUE on success.
  530. // FALSE on failure, use PCGetLastError.
  531. // Arguments: 0) PCid from PCOpen,
  532. // 1) pointer to structure to receive process data,
  533. // 2) size of this structure in bytes,
  534. // 3) [optional] location to store update counter to be supplied on update.
  535. // Note: If the process is a member of a job, the job's management rules will be
  536. // used instead of the process rules unless the job definition is missing.
  537. //======================================================================================//
  538. BOOL PCGetProcDetail( PCid target, PCProcDetail *pProcDetail, PCINT32 nByteCount, PCINT32 *nUpdateCtr )
  539. {
  540. if ( !PCIsValidPCId( target ) ) return FALSE;
  541. // Build request...
  542. PCBuildReq( target, PCOP_GET, PCTYPE_PROCDETAIL, pProcDetail,
  543. offsetof(PCProcDetail, vLength), nByteCount );
  544. // Send request, receive response and verify success...
  545. if ( !PCSendReceive( target ) ) return FALSE;
  546. // Pass appropriate data back to caller...
  547. PCCopyData( target, pProcDetail, 1, nByteCount, nUpdateCtr );
  548. return TRUE;
  549. }
  550. //======================================================================================//
  551. // PCGetJobDetail -- get full management and descriptive data associated with a job name.
  552. // Returns: TRUE on success.
  553. // FALSE on failure, use PCGetLastError.
  554. // Arguments: 0) PCid from PCOpen,
  555. // 1) pointer to structure to receive job data,
  556. // 2) size of this structure in bytes,
  557. // 3) [optional] location to store update counter to be supplied on update.
  558. //======================================================================================//
  559. BOOL PCGetJobDetail( PCid target, PCJobDetail *pJobDetail, PCINT32 nByteCount, PCINT32 *nUpdateCtr )
  560. {
  561. if ( !PCIsValidPCId( target ) ) return FALSE;
  562. // Build request...
  563. PCBuildReq( target, PCOP_GET, PCTYPE_JOBDETAIL, pJobDetail,
  564. offsetof(PCProcDetail, vLength), nByteCount );
  565. // Send request, receive response and verify success...
  566. if ( !PCSendReceive( target ) ) return FALSE;
  567. // Pass appropriate data back to caller...
  568. PCCopyData( target, pJobDetail, 1, nByteCount, nUpdateCtr );
  569. return TRUE;
  570. }
  571. //======================================================================================//
  572. // PCAddNameRule -- add a name rule to the name rule table.
  573. // Returns: 0 or greater to indicate the number of items in the response (may be incomplete).
  574. // -1 on failure, use PCGetLastError.
  575. // Arguments: 0) PCid from PCOpen,
  576. // 1) pointer to name rule to add,
  577. // 2) index of name rule line BEFORE which this addition is to occur (0-based),
  578. // 3) update counter returned from PCGetNameRules,
  579. // 4-6) [optional] same args as PCGetNameRules to return updated name rule table.
  580. //======================================================================================//
  581. PCINT32 PCAddNameRule( PCid target, PCNameRule *pRule, PCINT32 nIndex, PCINT32 nUpdateCtr,
  582. PCNameRule *pRuleList, PCINT32 nByteCount, PCINT32 nFirst, PCINT32 *nNewUpdateCtr )
  583. {
  584. if ( !PCIsValidPCId( target ) ) return -1;
  585. // Build request...
  586. PCINT32 maxItemsRequested = PCMaxItemCount( target, nByteCount, sizeof(PCNameRule) );
  587. PCBuildReq( target, PCOP_ADD, PCTYPE_NAMERULE,
  588. pRule, sizeof(PCNameRule), nByteCount,
  589. nIndex, maxItemsRequested, nFirst, nUpdateCtr );
  590. if ( pRuleList ) PCSetReqFlag( target, PCREQFLAG_DOLIST );
  591. // Send request, receive response and verify success...
  592. if ( !PCSendReceive( target ) ) return -1;
  593. // Pass appropriate data back to caller...
  594. if ( pRuleList )
  595. return PCCopyData( target, pRuleList, maxItemsRequested, nByteCount, nNewUpdateCtr );
  596. else return 0;
  597. }
  598. //======================================================================================//
  599. // PCReplNameRule -- Replace a name rule in the name rule table.
  600. // Returns: 0 or greater to indicate the number of items in the response (may be incomplete).
  601. // -1 on failure, use PCGetLastError.
  602. // Arguments: 0) PCid from PCOpen,
  603. // 1) pointer to name rule replacement data,
  604. // 2) index of name rule line to replace (0-based),
  605. // 3) update counter returned from PCGetNameRules,
  606. // 4-6) [optional] same args as PCGetNameRules to return updated name rule table.
  607. //======================================================================================//
  608. PCINT32 PCReplNameRule( PCid target, PCNameRule *pRule, PCINT32 nIndex, PCINT32 nUpdateCtr,
  609. PCNameRule *pRuleList, PCINT32 nByteCount, PCINT32 nFirst, PCINT32 *nNewUpdateCtr )
  610. {
  611. if ( !PCIsValidPCId( target ) ) return -1;
  612. // Build request...
  613. PCINT32 maxItemsRequested = PCMaxItemCount( target, nByteCount, sizeof(PCNameRule) );
  614. PCBuildReq( target, PCOP_REP, PCTYPE_NAMERULE,
  615. pRule, sizeof(PCNameRule), nByteCount,
  616. nIndex, maxItemsRequested, nFirst, nUpdateCtr );
  617. if ( pRuleList ) PCSetReqFlag( target, PCREQFLAG_DOLIST );
  618. // Send request, receive response and verify success...
  619. if ( !PCSendReceive( target ) ) return -1;
  620. // Pass appropriate data back to caller...
  621. if ( pRuleList )
  622. return PCCopyData( target, pRuleList, maxItemsRequested, nByteCount, nNewUpdateCtr );
  623. else return 0;
  624. }
  625. //======================================================================================//
  626. // PCDeleteNameRule -- Delete a name rule from the name rule table.
  627. // Returns: 0 or greater to indicate the number of items in the response (may be incomplete).
  628. // -1 on failure, use PCGetLastError.
  629. // Arguments: 0) PCid from PCOpen,
  630. // 1) index of name rule line to delete (0-based),
  631. // 2) update counter returned from PCGetNameRules,
  632. // 3-5) [optional] same args as PCGetNameRules to return updated name rule table.
  633. //======================================================================================//
  634. PCINT32 PCDeleteNameRule( PCid target, PCINT32 nIndex, PCINT32 nUpdateCtr,
  635. PCNameRule *pRuleList, PCINT32 nByteCount, PCINT32 nFirst, PCINT32 *nNewUpdateCtr )
  636. {
  637. if ( !PCIsValidPCId( target ) ) return -1;
  638. // Build request...
  639. PCINT32 maxItemsRequested = PCMaxItemCount( target, nByteCount, sizeof(PCNameRule) );
  640. PCBuildReq( target, PCOP_DEL, PCTYPE_NAMERULE,
  641. NULL, 0, nByteCount,
  642. nIndex, maxItemsRequested, nFirst, nUpdateCtr );
  643. if ( pRuleList ) PCSetReqFlag( target, PCREQFLAG_DOLIST );
  644. // Send request, receive response and verify success...
  645. if ( !PCSendReceive( target ) ) return -1;
  646. // Pass appropriate data back to caller...
  647. if ( pRuleList )
  648. return PCCopyData( target, pRuleList, maxItemsRequested, nByteCount, nNewUpdateCtr );
  649. else return 0;
  650. }
  651. //======================================================================================//
  652. // PCSwapNameRules -- Swap the order of two adjacent entries in the name rule table.
  653. // Note: This API is needed because the order of entires in the table is significant.
  654. // Returns: 0 or greater to indicate the number of items in the response (may be incomplete).
  655. // -1 on failure, use PCGetLastError.
  656. // Arguments: 0) PCid from PCOpen,
  657. // 1) index of name rule line to swap with line index+1 (0-based),
  658. // 2) update counter returned from PCGetNameRules,
  659. // 3-5) [optional] same args as PCGetNameRules to return updated name rule table.
  660. //======================================================================================//
  661. PCINT32 PCSwapNameRules( PCid target, PCINT32 nIndex, PCINT32 nUpdateCtr,
  662. PCNameRule *pRuleList, PCINT32 nByteCount, PCINT32 nFirst, PCINT32 *nNewUpdateCtr )
  663. {
  664. if ( !PCIsValidPCId( target ) ) return -1;
  665. // Build request...
  666. PCINT32 maxItemsRequested = PCMaxItemCount( target, nByteCount, sizeof(PCNameRule) );
  667. PCBuildReq( target, PCOP_ORD, PCTYPE_NAMERULE,
  668. NULL, 0, nByteCount, nIndex, maxItemsRequested, nFirst, nUpdateCtr );
  669. if ( pRuleList ) PCSetReqFlag( target, PCREQFLAG_DOLIST );
  670. // Send request, receive response and verify success...
  671. if ( !PCSendReceive( target ) ) return -1;
  672. // Pass appropriate data back to caller...
  673. if ( pRuleList )
  674. return PCCopyData( target, pRuleList, maxItemsRequested, nByteCount, nNewUpdateCtr );
  675. else return 0;
  676. }
  677. //======================================================================================//
  678. // PCAddProcDetail -- add a new process to the process management database.
  679. // Returns: TRUE on success.
  680. // FALSE on failure, use PCGetLastError.
  681. // Arguments: 0) PCid from PCOpen,
  682. // 1) pointer to process detail to add, name must not exist.
  683. // 2) [optional] pointer to buffer to retrieve updated proc summary for this entry.
  684. // Note: No update counter is needed for adding detail since add fails if the name
  685. // exists.
  686. //======================================================================================//
  687. BOOL PCAddProcDetail( PCid target, PCProcDetail *pProcDetail, PCProcSummary *pProcList )
  688. {
  689. if ( !PCIsValidPCId( target ) ) return FALSE;
  690. // Build request...
  691. PCBuildReq( target, PCOP_ADD, PCTYPE_PROCDETAIL, pProcDetail,
  692. (PCINT16) (offsetof(PCProcDetail, vData) + pProcDetail->vLength) );
  693. if ( pProcList ) PCSetReqFlag( target, PCREQFLAG_DOLIST );
  694. // Send request, receive response and verify success...
  695. if ( !PCSendReceive( target ) ) return FALSE;
  696. // Pass appropriate data back to caller...
  697. if ( pProcList )
  698. PCCopyData( target, pProcList, 1, sizeof(PCProcSummary) );
  699. return TRUE;
  700. }
  701. //======================================================================================//
  702. // PCDeleteProcDetail -- Delete a process from the process management database.
  703. // Returns: TRUE on success.
  704. // FALSE on failure, use PCGetLastError.
  705. // Arguments: 0) PCid from PCOpen,
  706. // 1) pointer to process detail to Delete, name must exist,
  707. // Note: No update counter is needed for deleting since delete fails if the name
  708. // doesn't exist.
  709. //======================================================================================//
  710. BOOL PCDeleteProcDetail( PCid target, PCProcDetail *pProcDetail )
  711. {
  712. if ( !PCIsValidPCId( target ) ) return FALSE;
  713. // Build request (note that only the summary portion is included)...
  714. PCBuildReq( target, PCOP_DEL, PCTYPE_PROCDETAIL, pProcDetail, sizeof( PCProcSummary ) );
  715. // Send request, receive response and verify success...
  716. return PCSendReceive( target );
  717. }
  718. //======================================================================================//
  719. // PCReplProcDetail -- Replace a process in the process management database.
  720. // Returns: TRUE on success.
  721. // FALSE on failure, use PCGetLastError.
  722. // Arguments: 0) PCid from PCOpen,
  723. // 1) pointer to process detail to replace, name must exist,
  724. // 2) update counter from PCGetProcDetail.
  725. // 3) [optional] pointer to buffer to retrieve updated proc summary for this entry.
  726. //======================================================================================//
  727. BOOL PCReplProcDetail( PCid target, PCProcDetail *pProcDetail, PCINT32 nUpdateCtr, PCProcSummary *pProcList )
  728. {
  729. if ( !PCIsValidPCId( target ) ) return FALSE;
  730. // Build request...
  731. PCBuildReq( target, PCOP_REP, PCTYPE_PROCDETAIL, pProcDetail,
  732. (PCINT16) (offsetof(PCProcDetail, vData) + pProcDetail->vLength), 0, 0, 1, 0, nUpdateCtr );
  733. if ( pProcList ) PCSetReqFlag( target, PCREQFLAG_DOLIST );
  734. // Send request, receive response and verify success...
  735. if ( !PCSendReceive( target ) ) return FALSE;
  736. // Pass appropriate data back to caller...
  737. if ( pProcList )
  738. PCCopyData( target, pProcList, 1, sizeof(PCProcSummary) );
  739. return TRUE;
  740. }
  741. //======================================================================================//
  742. // PCAddJobDetail -- add a new job definition to the job management database.
  743. // Returns: 1 on success (treat as TRUE or as a count if summary item requested).
  744. // FALSE on failure, use PCGetLastError.
  745. // Arguments: 0) PCid from PCOpen,
  746. // 1) pointer to job detail to add, name must not exist,
  747. // 2) [optional] pointer to buffer to retrieve updated job summary for this entry.
  748. // Note: No update counter is needed for adding since add fails if the name
  749. // exists.
  750. //======================================================================================//
  751. BOOL PCAddJobDetail( PCid target, PCJobDetail *pJobDetail, PCJobSummary *pJobList )
  752. {
  753. if ( !PCIsValidPCId( target ) ) return FALSE;
  754. // Build request...
  755. PCBuildReq( target, PCOP_ADD, PCTYPE_JOBDETAIL, pJobDetail,
  756. (PCINT16) (offsetof(PCJobDetail, vData) + pJobDetail->vLength) );
  757. if ( pJobList ) PCSetReqFlag( target, PCREQFLAG_DOLIST );
  758. // Send request, receive response and verify success...
  759. if ( !PCSendReceive( target ) ) return FALSE;
  760. // Pass appropriate data back to caller...
  761. if ( pJobList )
  762. PCCopyData( target, pJobList, 1, sizeof(PCJobSummary) );
  763. return TRUE;
  764. }
  765. //======================================================================================//
  766. // PCDeleteJobDetail -- Delete a job from the job management database.
  767. // Returns: TRUE on success.
  768. // FALSE on failure, use PCGetLastError.
  769. // Arguments: 0) PCid from PCOpen,
  770. // 1) pointer to job detail to Delete, name must exist,
  771. // Note: No update counter is needed for deleting since delete fails if the name
  772. // doesn't exist.
  773. //======================================================================================//
  774. BOOL PCDeleteJobDetail( PCid target, PCJobDetail *pJobDetail )
  775. {
  776. if ( !PCIsValidPCId( target ) ) return FALSE;
  777. // Build request (note that only the summary portion is included)...
  778. PCBuildReq( target, PCOP_DEL, PCTYPE_JOBDETAIL, pJobDetail, sizeof( PCJobSummary ) );
  779. // Send request, receive response and verify success...
  780. return PCSendReceive( target );
  781. }
  782. //======================================================================================//
  783. // PCReplJobDetail -- Replace a job in the job management database.
  784. // Returns: TRUE on success.
  785. // FALSE on failure, use PCGetLastError.
  786. // Arguments: 0) PCid from PCOpen,
  787. // 1) pointer to job detail to replace, name must exist,
  788. // 2) update counter from PCGetJobDetail.
  789. // 3) [optional] pointer to buffer to retrieve updated job summary for this entry.
  790. //======================================================================================//
  791. BOOL PCReplJobDetail( PCid target, PCJobDetail *pJobDetail, PCINT32 nUpdateCtr, PCJobSummary *pJobList )
  792. {
  793. if ( !PCIsValidPCId( target ) ) return FALSE;
  794. // Build request...
  795. PCBuildReq( target, PCOP_REP, PCTYPE_JOBDETAIL, pJobDetail,
  796. (PCINT16) (offsetof(PCJobDetail, vData) + pJobDetail->vLength), 0, 0, 1, 0, nUpdateCtr );
  797. if ( pJobList ) PCSetReqFlag( target, PCREQFLAG_DOLIST );
  798. // Send request, receive response and verify success...
  799. if ( !PCSendReceive( target ) ) return FALSE;
  800. // Pass appropriate data back to caller...
  801. if ( pJobList )
  802. PCCopyData( target, pJobList, 1, sizeof(PCJobSummary) );
  803. return TRUE;
  804. }