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.

506 lines
14 KiB

  1. /*++ BUILD Version: 0000 // Increment this if a change has global effects
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. setup_browser.c
  5. Abstract:
  6. This is used by syssetup to enable net browser. It's generated from various files under
  7. ds\netapi\svcdlls\bworser\common. Do not edit by hand.
  8. Revision History:
  9. --*/
  10. #include <lmcons.h> // NET_API_STATUS
  11. #include <lmerr.h> // NetError codes
  12. #include <ntddbrow.h>
  13. #include <netlibnt.h> // NetpNtStatusToApiStatus
  14. #include <align.h>
  15. #define NetpAssert(x)
  16. //
  17. // Buffer allocation size for enumeration output buffer.
  18. //
  19. #define INITIAL_ALLOCATION_SIZE 48*1024 // First attempt size (48K)
  20. #define FUDGE_FACTOR_SIZE 1024 // Second try TotalBytesNeeded
  21. // plus this amount
  22. //
  23. // prototypes
  24. //
  25. #ifdef ENABLE_PSEUDO_BROWSER
  26. DWORD
  27. IsBrowserEnabled(
  28. IN OPTIONAL LPTSTR Section,
  29. IN LPTSTR Key,
  30. IN BOOL fDefault
  31. );
  32. DWORD
  33. GetBrowserValue(
  34. IN OPTIONAL LPTSTR Section,
  35. IN LPTSTR Key,
  36. OUT PDWORD pdwValue
  37. );
  38. #endif
  39. //
  40. // Implementation
  41. //
  42. NET_API_STATUS
  43. BrDgReceiverIoControlEx(
  44. IN HANDLE FileHandle,
  45. IN ULONG DgReceiverControlCode,
  46. IN PLMDR_REQUEST_PACKET Drp,
  47. IN ULONG DrpSize,
  48. IN PVOID SecondBuffer OPTIONAL,
  49. IN ULONG SecondBufferLength,
  50. OUT PULONG Information OPTIONAL,
  51. IN BOOLEAN WaitForCompletion
  52. )
  53. /*++
  54. Routine Description:
  55. Arguments:
  56. FileHandle - Supplies a handle to the file or device on which the service
  57. is being performed.
  58. DgReceiverControlCode - Supplies the NtDeviceIoControlFile function code
  59. given to the datagram receiver.
  60. Drp - Supplies the datagram receiver request packet.
  61. DrpSize - Supplies the length of the datagram receiver request packet.
  62. SecondBuffer - Supplies the second buffer in call to NtDeviceIoControlFile.
  63. SecondBufferLength - Supplies the length of the second buffer.
  64. Information - Returns the information field of the I/O status block.
  65. Return Value:
  66. NET_API_STATUS - NERR_Success or reason for failure.
  67. --*/
  68. {
  69. NTSTATUS ntstatus;
  70. IO_STATUS_BLOCK IoStatusBlock;
  71. PLMDR_REQUEST_PACKET RealDrp;
  72. HANDLE CompletionEvent;
  73. LPBYTE Where;
  74. if (FileHandle == NULL) {
  75. return ERROR_NOT_SUPPORTED;
  76. }
  77. //
  78. // Allocate a copy of the request packet where we can put the transport and
  79. // emulated domain name in the packet itself.
  80. //
  81. RealDrp = (PLMDR_REQUEST_PACKET) MIDL_user_allocate(DrpSize+
  82. Drp->TransportName.Length+sizeof(WCHAR)+
  83. Drp->EmulatedDomainName.Length+sizeof(WCHAR) );
  84. if (RealDrp == NULL) {
  85. return ERROR_NOT_ENOUGH_MEMORY;
  86. }
  87. //
  88. // Copy the request packet into the local copy.
  89. //
  90. RtlCopyMemory(RealDrp, Drp, DrpSize);
  91. Where = (LPBYTE)RealDrp+DrpSize;
  92. if (Drp->TransportName.Length != 0) {
  93. RealDrp->TransportName.Buffer = (LPWSTR)Where;
  94. RealDrp->TransportName.MaximumLength = Drp->TransportName.Length+sizeof(WCHAR);
  95. RtlCopyUnicodeString(&RealDrp->TransportName, &Drp->TransportName);
  96. Where += RealDrp->TransportName.MaximumLength;
  97. }
  98. if (Drp->EmulatedDomainName.Length != 0) {
  99. RealDrp->EmulatedDomainName.Buffer = (LPWSTR)Where;
  100. RealDrp->EmulatedDomainName.MaximumLength = Drp->EmulatedDomainName.Length+sizeof(WCHAR);
  101. RtlCopyUnicodeString(&RealDrp->EmulatedDomainName, &Drp->EmulatedDomainName);
  102. Where += RealDrp->EmulatedDomainName.MaximumLength;
  103. }
  104. //
  105. // Create a completion event
  106. //
  107. CompletionEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  108. if (CompletionEvent == NULL) {
  109. MIDL_user_free(RealDrp);
  110. return(GetLastError());
  111. }
  112. //
  113. // Send the request to the Datagram Receiver DD.
  114. //
  115. ntstatus = NtDeviceIoControlFile(
  116. FileHandle,
  117. CompletionEvent,
  118. NULL,
  119. NULL,
  120. &IoStatusBlock,
  121. DgReceiverControlCode,
  122. RealDrp,
  123. (ULONG)(Where-(LPBYTE)RealDrp),
  124. SecondBuffer,
  125. SecondBufferLength
  126. );
  127. if (NT_SUCCESS(ntstatus)) {
  128. //
  129. // If we need to wait for completion (synchronous) and
  130. // If pending was returned, then wait until the request completes.
  131. //
  132. if ( WaitForCompletion && (ntstatus == STATUS_PENDING) ) {
  133. do {
  134. ntstatus = WaitForSingleObjectEx(CompletionEvent, 0xffffffff, TRUE);
  135. } while ( ntstatus == WAIT_IO_COMPLETION );
  136. }
  137. if (NT_SUCCESS(ntstatus)) {
  138. ntstatus = IoStatusBlock.Status;
  139. }
  140. }
  141. if (ARGUMENT_PRESENT(Information)) {
  142. *Information = (ULONG)IoStatusBlock.Information;
  143. }
  144. MIDL_user_free(RealDrp);
  145. CloseHandle(CompletionEvent);
  146. return NetpNtStatusToApiStatus(ntstatus);
  147. }
  148. NET_API_STATUS
  149. BrDgReceiverIoControl(
  150. IN HANDLE FileHandle,
  151. IN ULONG DgReceiverControlCode,
  152. IN PLMDR_REQUEST_PACKET Drp,
  153. IN ULONG DrpSize,
  154. IN PVOID SecondBuffer OPTIONAL,
  155. IN ULONG SecondBufferLength,
  156. OUT PULONG Information OPTIONAL
  157. )
  158. {
  159. return BrDgReceiverIoControlEx(
  160. FileHandle,
  161. DgReceiverControlCode,
  162. Drp,
  163. DrpSize,
  164. SecondBuffer,
  165. SecondBufferLength,
  166. Information,
  167. TRUE
  168. );
  169. }
  170. NET_API_STATUS
  171. DeviceControlGetInfo(
  172. IN HANDLE FileHandle,
  173. IN ULONG DeviceControlCode,
  174. IN PVOID RequestPacket,
  175. IN ULONG RequestPacketLength,
  176. OUT LPVOID *OutputBuffer,
  177. IN ULONG PreferedMaximumLength,
  178. IN ULONG BufferHintSize,
  179. OUT PULONG Information OPTIONAL
  180. )
  181. /*++
  182. Routine Description:
  183. This function allocates the buffer and fill it with the information
  184. that is retrieved from the datagram receiver.
  185. Arguments:
  186. DeviceDriverType - Supplies the value which indicates whether to call
  187. the datagram receiver.
  188. FileHandle - Supplies a handle to the file or device of which to get
  189. information about.
  190. DeviceControlCode - Supplies the NtFsControlFile or NtIoDeviceControlFile
  191. function control code.
  192. RequestPacket - Supplies a pointer to the device request packet.
  193. RrequestPacketLength - Supplies the length of the device request packet.
  194. OutputBuffer - Returns a pointer to the buffer allocated by this routine
  195. which contains the use information requested. This pointer is set to
  196. NULL if return code is not NERR_Success.
  197. PreferedMaximumLength - Supplies the number of bytes of information to
  198. return in the buffer. If this value is MAXULONG, we will try to
  199. return all available information if there is enough memory resource.
  200. BufferHintSize - Supplies the hint size of the output buffer so that the
  201. memory allocated for the initial buffer will most likely be large
  202. enough to hold all requested data.
  203. Information - Returns the information code from the NtFsControlFile or
  204. NtIoDeviceControlFile call.
  205. Return Value:
  206. NET_API_STATUS - NERR_Success or reason for failure.
  207. --*/
  208. {
  209. NET_API_STATUS status;
  210. NTSTATUS ntstatus;
  211. DWORD OutputBufferLength;
  212. DWORD TotalBytesNeeded = 1;
  213. ULONG OriginalResumeKey;
  214. IO_STATUS_BLOCK IoStatusBlock;
  215. PLMDR_REQUEST_PACKET Drrp = (PLMDR_REQUEST_PACKET) RequestPacket;
  216. HANDLE CompletionEvent;
  217. OriginalResumeKey = Drrp->Parameters.EnumerateNames.ResumeHandle;
  218. //
  219. // If PreferedMaximumLength is MAXULONG, then we are supposed to get all
  220. // the information, regardless of size. Allocate the output buffer of a
  221. // reasonable size and try to use it. If this fails, the Redirector FSD
  222. // will say how much we need to allocate.
  223. //
  224. if (PreferedMaximumLength == MAXULONG) {
  225. OutputBufferLength = (BufferHintSize) ?
  226. BufferHintSize :
  227. INITIAL_ALLOCATION_SIZE;
  228. }
  229. else {
  230. OutputBufferLength = PreferedMaximumLength;
  231. }
  232. OutputBufferLength = ROUND_UP_COUNT(OutputBufferLength, ALIGN_WCHAR);
  233. if ((*OutputBuffer = MIDL_user_allocate(OutputBufferLength)) == NULL) {
  234. return ERROR_NOT_ENOUGH_MEMORY;
  235. }
  236. RtlZeroMemory((PVOID) *OutputBuffer, OutputBufferLength);
  237. CompletionEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  238. if (CompletionEvent == NULL) {
  239. MIDL_user_free(*OutputBuffer);
  240. *OutputBuffer = NULL;
  241. return(GetLastError());
  242. }
  243. Drrp->Parameters.EnumerateServers.EntriesRead = 0;
  244. //
  245. // Make the request of the Datagram Receiver
  246. //
  247. ntstatus = NtDeviceIoControlFile(
  248. FileHandle,
  249. CompletionEvent,
  250. NULL, // APC routine
  251. NULL, // APC context
  252. &IoStatusBlock,
  253. DeviceControlCode,
  254. Drrp,
  255. RequestPacketLength,
  256. *OutputBuffer,
  257. OutputBufferLength
  258. );
  259. if (NT_SUCCESS(ntstatus)) {
  260. //
  261. // If pending was returned, then wait until the request completes.
  262. //
  263. if (ntstatus == STATUS_PENDING) {
  264. do {
  265. ntstatus = WaitForSingleObjectEx(CompletionEvent, 0xffffffff, TRUE);
  266. } while ( ntstatus == WAIT_IO_COMPLETION );
  267. }
  268. if (NT_SUCCESS(ntstatus)) {
  269. ntstatus = IoStatusBlock.Status;
  270. }
  271. }
  272. //
  273. // Map NT status to Win error
  274. //
  275. status = NetpNtStatusToApiStatus(ntstatus);
  276. if (status == ERROR_MORE_DATA) {
  277. NetpAssert(
  278. FIELD_OFFSET(
  279. LMDR_REQUEST_PACKET,
  280. Parameters.EnumerateNames.TotalBytesNeeded
  281. ) ==
  282. FIELD_OFFSET(
  283. LMDR_REQUEST_PACKET,
  284. Parameters.EnumerateServers.TotalBytesNeeded
  285. )
  286. );
  287. NetpAssert(
  288. FIELD_OFFSET(
  289. LMDR_REQUEST_PACKET,
  290. Parameters.GetBrowserServerList.TotalBytesNeeded
  291. ) ==
  292. FIELD_OFFSET(
  293. LMDR_REQUEST_PACKET,
  294. Parameters.EnumerateServers.TotalBytesNeeded
  295. )
  296. );
  297. TotalBytesNeeded = Drrp->Parameters.EnumerateNames.TotalBytesNeeded;
  298. }
  299. if ((TotalBytesNeeded > OutputBufferLength) &&
  300. (PreferedMaximumLength == MAXULONG)) {
  301. PLMDR_REQUEST_PACKET Drrp = (PLMDR_REQUEST_PACKET) RequestPacket;
  302. //
  303. // Initial output buffer allocated was too small and we need to return
  304. // all data. First free the output buffer before allocating the
  305. // required size plus a fudge factor just in case the amount of data
  306. // grew.
  307. //
  308. MIDL_user_free(*OutputBuffer);
  309. OutputBufferLength =
  310. ROUND_UP_COUNT((TotalBytesNeeded + FUDGE_FACTOR_SIZE),
  311. ALIGN_WCHAR);
  312. if ((*OutputBuffer = MIDL_user_allocate(OutputBufferLength)) == NULL) {
  313. return ERROR_NOT_ENOUGH_MEMORY;
  314. }
  315. RtlZeroMemory((PVOID) *OutputBuffer, OutputBufferLength);
  316. NetpAssert(
  317. FIELD_OFFSET(
  318. LMDR_REQUEST_PACKET,
  319. Parameters.EnumerateNames.ResumeHandle
  320. ) ==
  321. FIELD_OFFSET(
  322. LMDR_REQUEST_PACKET,
  323. Parameters.EnumerateServers.ResumeHandle
  324. )
  325. );
  326. NetpAssert(
  327. FIELD_OFFSET(
  328. LMDR_REQUEST_PACKET,
  329. Parameters.EnumerateNames.ResumeHandle
  330. ) ==
  331. FIELD_OFFSET(
  332. LMDR_REQUEST_PACKET,
  333. Parameters.GetBrowserServerList.ResumeHandle
  334. )
  335. );
  336. Drrp->Parameters.EnumerateNames.ResumeHandle = OriginalResumeKey;
  337. Drrp->Parameters.EnumerateServers.EntriesRead = 0;
  338. //
  339. // Make the request of the Datagram Receiver
  340. //
  341. ntstatus = NtDeviceIoControlFile(
  342. FileHandle,
  343. CompletionEvent,
  344. NULL, // APC routine
  345. NULL, // APC context
  346. &IoStatusBlock,
  347. DeviceControlCode,
  348. Drrp,
  349. RequestPacketLength,
  350. *OutputBuffer,
  351. OutputBufferLength
  352. );
  353. if (NT_SUCCESS(ntstatus)) {
  354. //
  355. // If pending was returned, then wait until the request completes.
  356. //
  357. if (ntstatus == STATUS_PENDING) {
  358. do {
  359. ntstatus = WaitForSingleObjectEx(CompletionEvent, 0xffffffff, TRUE);
  360. } while ( ntstatus == WAIT_IO_COMPLETION );
  361. }
  362. if (NT_SUCCESS(ntstatus)) {
  363. ntstatus = IoStatusBlock.Status;
  364. }
  365. }
  366. status = NetpNtStatusToApiStatus(ntstatus);
  367. }
  368. //
  369. // If not successful in getting any data, or if the caller asked for
  370. // all available data with PreferedMaximumLength == MAXULONG and
  371. // our buffer overflowed, free the output buffer and set its pointer
  372. // to NULL.
  373. //
  374. if ((status != NERR_Success && status != ERROR_MORE_DATA) ||
  375. (TotalBytesNeeded == 0) ||
  376. (PreferedMaximumLength == MAXULONG && status == ERROR_MORE_DATA) ||
  377. (Drrp->Parameters.EnumerateServers.EntriesRead == 0)) {
  378. MIDL_user_free(*OutputBuffer);
  379. *OutputBuffer = NULL;
  380. //
  381. // PreferedMaximumLength == MAXULONG and buffer overflowed means
  382. // we do not have enough memory to satisfy the request.
  383. //
  384. if (status == ERROR_MORE_DATA) {
  385. status = ERROR_NOT_ENOUGH_MEMORY;
  386. }
  387. }
  388. CloseHandle(CompletionEvent);
  389. return status;
  390. UNREFERENCED_PARAMETER(Information);
  391. }