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.

263 lines
8.8 KiB

  1. /*++
  2. Copyright (c) 1991-1993 Microsoft Corporation
  3. Module Name:
  4. SvcEnum.c
  5. Abstract:
  6. This file contains the RpcXlate code to handle the Service APIs.
  7. Author:
  8. John Rogers (JohnRo) 13-Sep-1991
  9. Environment:
  10. Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
  11. Requires ANSI C extensions: slash-slash comments, long external names.
  12. Revision History:
  13. 13-Sep-1991 JohnRo
  14. Created.
  15. 18-Sep-1991 JohnRo
  16. Handle ERROR_MORE_DATA.
  17. 21-Nov-1991 JohnRo
  18. Removed NT dependencies to reduce recompiles.
  19. 25-Nov-1991 JohnRo
  20. Assert to check for possible infinite loop.
  21. 07-Feb-1992 JohnRo
  22. Use NetApiBufferAllocate() instead of private version.
  23. 27-Jan-1993 JohnRo
  24. RAID 8926: NetConnectionEnum to downlevel: memory leak on error.
  25. Also prevent possible infinite loop.
  26. --*/
  27. // These must be included first:
  28. #include <windef.h> // IN, DWORD, etc.
  29. #include <lmcons.h> // DEVLEN, NET_API_STATUS, etc.
  30. // These may be included in any order:
  31. #include <apinums.h> // API_ equates.
  32. #include <lmapibuf.h> // NetApiBufferFree().
  33. #include <lmerr.h> // ERROR_ and NERR_ equates.
  34. #include <lmsvc.h> // API's data structures.
  35. #include <netdebug.h> // NetpAssert().
  36. #include <netlib.h> // NetpAdjustPreferredMaximum().
  37. #include <prefix.h> // PREFIX_ equates.
  38. #include <rap.h> // LPDESC.
  39. #include <remdef.h> // REM16_, REM32_, REMSmb_ equates.
  40. #include <rx.h> // RxRemoteApi().
  41. #include <rxp.h> // RxpFatalErrorCode().
  42. #include <rxsvc.h> // My prototype(s).
  43. #include <strucinf.h> // NetpServiceStructureInfo().
  44. #define SERVICE_ARRAY_OVERHEAD_SIZE 0
  45. NET_API_STATUS
  46. RxNetServiceEnum (
  47. IN LPTSTR UncServerName,
  48. IN DWORD Level,
  49. OUT LPBYTE *BufPtr,
  50. IN DWORD PreferedMaximumSize,
  51. OUT LPDWORD EntriesRead,
  52. OUT LPDWORD TotalEntries,
  53. IN OUT LPDWORD ResumeHandle OPTIONAL
  54. )
  55. /*++
  56. Routine Description:
  57. RxNetServiceEnum performs the same function as NetServiceEnum,
  58. except that the server name is known to refer to a downlevel server.
  59. Arguments:
  60. (Same as NetServiceEnum, except UncServerName must not be null, and
  61. must not refer to the local computer.)
  62. Return Value:
  63. (Same as NetServiceEnum.)
  64. --*/
  65. {
  66. LPDESC DataDesc16;
  67. LPDESC DataDesc32;
  68. LPDESC DataDescSmb;
  69. DWORD EntriesToAllocate;
  70. LPVOID InfoArray = NULL;
  71. DWORD InfoArraySize;
  72. DWORD MaxEntrySize;
  73. NET_API_STATUS Status;
  74. LPSERVICE_INFO_2 serviceInfo2;
  75. LPSERVICE_INFO_1 serviceInfo1;
  76. DWORD i;
  77. UNREFERENCED_PARAMETER(ResumeHandle);
  78. // Make sure caller didn't mess up.
  79. NetpAssert(UncServerName != NULL);
  80. if (BufPtr == NULL) {
  81. return (ERROR_INVALID_PARAMETER);
  82. }
  83. // Assume something might go wrong, and make error paths easier to
  84. // code. Also, check for a bad pointer before we do anything.
  85. *BufPtr = NULL;
  86. Status = NetpServiceStructureInfo (
  87. Level,
  88. PARMNUM_ALL, // want all fields.
  89. TRUE, // want native sizes.
  90. & DataDesc16,
  91. & DataDesc32,
  92. & DataDescSmb,
  93. & MaxEntrySize, // API buffer size 32
  94. NULL, // don't need fixed size
  95. NULL // don't need string size
  96. );
  97. if (Status != NERR_Success) {
  98. *BufPtr = NULL;
  99. return (Status);
  100. }
  101. //
  102. // Downlevel servers don't support resume handles, and we don't
  103. // have a way to say "close this resume handle" even if we wanted to
  104. // emulate them here. Therefore we have to do everthing in one shot.
  105. // So, the first time around, we'll try using the caller's prefered
  106. // maximum, but we will enlarge that until we can get everything in one
  107. // buffer.
  108. //
  109. // First time: try caller's prefered maximum.
  110. NetpAdjustPreferedMaximum (
  111. PreferedMaximumSize, // caller's request
  112. MaxEntrySize, // byte count per array element
  113. SERVICE_ARRAY_OVERHEAD_SIZE,// num bytes overhead to show array end
  114. NULL, // we'll compute byte counts ourselves.
  115. & EntriesToAllocate); // num of entries we can get.
  116. //
  117. // Loop until we have enough memory or we die for some other reason.
  118. //
  119. do {
  120. //
  121. // Figure out how much memory we need, within the protocol limit.
  122. //
  123. InfoArraySize = (EntriesToAllocate * MaxEntrySize)
  124. + SERVICE_ARRAY_OVERHEAD_SIZE;
  125. if (InfoArraySize > MAX_TRANSACT_RET_DATA_SIZE) {
  126. InfoArraySize = MAX_TRANSACT_RET_DATA_SIZE;
  127. }
  128. //
  129. // Remote the API, which will allocate the array for us.
  130. //
  131. Status = RxRemoteApi(
  132. API_WServiceEnum, // api number
  133. UncServerName, // \\servername
  134. REMSmb_NetServiceEnum_P, // parm desc (SMB version)
  135. DataDesc16,
  136. DataDesc32,
  137. DataDescSmb,
  138. NULL, // no aux desc 16
  139. NULL, // no aux desc 32
  140. NULL, // no aux desc SMB
  141. ALLOCATE_RESPONSE, // flags: not a null session API
  142. // rest of API's arguments in 32-bit LM 2.x format:
  143. Level, // sLevel: info level
  144. & InfoArray, // Buffer: array (alloc for us)
  145. InfoArraySize, // Buffer: array size in bytes
  146. EntriesRead, // pcEntriesRead
  147. TotalEntries); // pcTotalAvail
  148. //
  149. // If the server returned ERROR_MORE_DATA, free the buffer and try
  150. // again. (Actually, if we already tried 64K, then forget it.)
  151. //
  152. NetpAssert( InfoArraySize <= MAX_TRANSACT_RET_DATA_SIZE );
  153. if (Status != ERROR_MORE_DATA) {
  154. break;
  155. } else if (InfoArraySize == MAX_TRANSACT_RET_DATA_SIZE) {
  156. NetpKdPrint(( PREFIX_NETAPI
  157. "RxNetServiceEnum: "
  158. "**WARNING** protocol limit reached (64KB).\n" ));
  159. break;
  160. }
  161. (void) NetApiBufferFree( InfoArray );
  162. InfoArray = NULL;
  163. NetpAssert( EntriesToAllocate < *TotalEntries );
  164. EntriesToAllocate = *TotalEntries;
  165. } while (Status == ERROR_MORE_DATA);
  166. if (! RxpFatalErrorCode(Status)) {
  167. DWORD installState;
  168. *BufPtr = InfoArray;
  169. if (Level == 2) {
  170. //
  171. // Make the DisplayName pointer point to the service name.
  172. //
  173. serviceInfo2 = (LPSERVICE_INFO_2)InfoArray;
  174. for (i=0;i<*EntriesRead ;i++) {
  175. (serviceInfo2[i]).svci2_display_name = (serviceInfo2[i]).svci2_name;
  176. //
  177. // if INSTALL or UNINSTALL is PENDING, then force the upper
  178. // bits to 0. This is to prevent the upper bits of the wait
  179. // hint from getting accidentally set. Downlevel should never
  180. // use more than FF for waithint.
  181. //
  182. installState = (serviceInfo2[i]).svci2_status & SERVICE_INSTALL_STATE;
  183. if ((installState == SERVICE_INSTALL_PENDING) ||
  184. (installState == SERVICE_UNINSTALL_PENDING)) {
  185. (serviceInfo2[i]).svci2_code &= SERVICE_RESRV_MASK;
  186. }
  187. }
  188. }
  189. if (Level == 1) {
  190. serviceInfo1 = (LPSERVICE_INFO_1)InfoArray;
  191. for (i=0;i<*EntriesRead ;i++) {
  192. //
  193. // if INSTALL or UNINSTALL is PENDING, then force the upper
  194. // bits to 0. This is to prevent the upper bits of the wait
  195. // hint from getting accidentally set. Downlevel should never
  196. // use more than FF for waithint.
  197. //
  198. installState = (serviceInfo1[i]).svci1_status & SERVICE_INSTALL_STATE;
  199. if ((installState == SERVICE_INSTALL_PENDING) ||
  200. (installState == SERVICE_UNINSTALL_PENDING)) {
  201. (serviceInfo1[i]).svci1_code &= SERVICE_RESRV_MASK;
  202. }
  203. }
  204. }
  205. } else {
  206. if (InfoArray != NULL) {
  207. (VOID) NetApiBufferFree( InfoArray );
  208. }
  209. NetpAssert( *BufPtr == NULL );
  210. }
  211. return (Status);
  212. } // RxNetServiceEnum