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.

481 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. BrDgReceiverIoControl(
  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. )
  52. /*++
  53. Routine Description:
  54. Arguments:
  55. FileHandle - Supplies a handle to the file or device on which the service
  56. is being performed.
  57. DgReceiverControlCode - Supplies the NtDeviceIoControlFile function code
  58. given to the datagram receiver.
  59. Drp - Supplies the datagram receiver request packet.
  60. DrpSize - Supplies the length of the datagram receiver request packet.
  61. SecondBuffer - Supplies the second buffer in call to NtDeviceIoControlFile.
  62. SecondBufferLength - Supplies the length of the second buffer.
  63. Information - Returns the information field of the I/O status block.
  64. Return Value:
  65. NET_API_STATUS - NERR_Success or reason for failure.
  66. --*/
  67. {
  68. NTSTATUS ntstatus;
  69. IO_STATUS_BLOCK IoStatusBlock;
  70. PLMDR_REQUEST_PACKET RealDrp;
  71. HANDLE CompletionEvent;
  72. LPBYTE Where;
  73. if (FileHandle == NULL) {
  74. return ERROR_NOT_SUPPORTED;
  75. }
  76. //
  77. // Allocate a copy of the request packet where we can put the transport and
  78. // emulated domain name in the packet itself.
  79. //
  80. RealDrp = (PLMDR_REQUEST_PACKET) MIDL_user_allocate(DrpSize+
  81. Drp->TransportName.Length+sizeof(WCHAR)+
  82. Drp->EmulatedDomainName.Length+sizeof(WCHAR) );
  83. if (RealDrp == NULL) {
  84. return ERROR_NOT_ENOUGH_MEMORY;
  85. }
  86. //
  87. // Copy the request packet into the local copy.
  88. //
  89. RtlCopyMemory(RealDrp, Drp, DrpSize);
  90. Where = (LPBYTE)RealDrp+DrpSize;
  91. if (Drp->TransportName.Length != 0) {
  92. RealDrp->TransportName.Buffer = (LPWSTR)Where;
  93. RealDrp->TransportName.MaximumLength = Drp->TransportName.Length+sizeof(WCHAR);
  94. RtlCopyUnicodeString(&RealDrp->TransportName, &Drp->TransportName);
  95. Where += RealDrp->TransportName.MaximumLength;
  96. }
  97. if (Drp->EmulatedDomainName.Length != 0) {
  98. RealDrp->EmulatedDomainName.Buffer = (LPWSTR)Where;
  99. RealDrp->EmulatedDomainName.MaximumLength = Drp->EmulatedDomainName.Length+sizeof(WCHAR);
  100. RtlCopyUnicodeString(&RealDrp->EmulatedDomainName, &Drp->EmulatedDomainName);
  101. Where += RealDrp->EmulatedDomainName.MaximumLength;
  102. }
  103. //
  104. // Create a completion event
  105. //
  106. CompletionEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  107. if (CompletionEvent == NULL) {
  108. MIDL_user_free(RealDrp);
  109. return(GetLastError());
  110. }
  111. //
  112. // Send the request to the Datagram Receiver DD.
  113. //
  114. ntstatus = NtDeviceIoControlFile(
  115. FileHandle,
  116. CompletionEvent,
  117. NULL,
  118. NULL,
  119. &IoStatusBlock,
  120. DgReceiverControlCode,
  121. RealDrp,
  122. (ULONG)(Where-(LPBYTE)RealDrp),
  123. SecondBuffer,
  124. SecondBufferLength
  125. );
  126. if (NT_SUCCESS(ntstatus)) {
  127. //
  128. // If pending was returned, then wait until the request completes.
  129. //
  130. if (ntstatus == STATUS_PENDING) {
  131. do {
  132. ntstatus = WaitForSingleObjectEx(CompletionEvent, 0xffffffff, TRUE);
  133. } while ( ntstatus == WAIT_IO_COMPLETION );
  134. }
  135. if (NT_SUCCESS(ntstatus)) {
  136. ntstatus = IoStatusBlock.Status;
  137. }
  138. }
  139. if (ARGUMENT_PRESENT(Information)) {
  140. *Information = (ULONG)IoStatusBlock.Information;
  141. }
  142. MIDL_user_free(RealDrp);
  143. CloseHandle(CompletionEvent);
  144. return NetpNtStatusToApiStatus(ntstatus);
  145. }
  146. NET_API_STATUS
  147. DeviceControlGetInfo(
  148. IN HANDLE FileHandle,
  149. IN ULONG DeviceControlCode,
  150. IN PVOID RequestPacket,
  151. IN ULONG RequestPacketLength,
  152. OUT LPVOID *OutputBuffer,
  153. IN ULONG PreferedMaximumLength,
  154. IN ULONG BufferHintSize,
  155. OUT PULONG Information OPTIONAL
  156. )
  157. /*++
  158. Routine Description:
  159. This function allocates the buffer and fill it with the information
  160. that is retrieved from the datagram receiver.
  161. Arguments:
  162. DeviceDriverType - Supplies the value which indicates whether to call
  163. the datagram receiver.
  164. FileHandle - Supplies a handle to the file or device of which to get
  165. information about.
  166. DeviceControlCode - Supplies the NtFsControlFile or NtIoDeviceControlFile
  167. function control code.
  168. RequestPacket - Supplies a pointer to the device request packet.
  169. RrequestPacketLength - Supplies the length of the device request packet.
  170. OutputBuffer - Returns a pointer to the buffer allocated by this routine
  171. which contains the use information requested. This pointer is set to
  172. NULL if return code is not NERR_Success.
  173. PreferedMaximumLength - Supplies the number of bytes of information to
  174. return in the buffer. If this value is MAXULONG, we will try to
  175. return all available information if there is enough memory resource.
  176. BufferHintSize - Supplies the hint size of the output buffer so that the
  177. memory allocated for the initial buffer will most likely be large
  178. enough to hold all requested data.
  179. Information - Returns the information code from the NtFsControlFile or
  180. NtIoDeviceControlFile call.
  181. Return Value:
  182. NET_API_STATUS - NERR_Success or reason for failure.
  183. --*/
  184. {
  185. NET_API_STATUS status;
  186. NTSTATUS ntstatus;
  187. DWORD OutputBufferLength;
  188. DWORD TotalBytesNeeded = 1;
  189. ULONG OriginalResumeKey;
  190. IO_STATUS_BLOCK IoStatusBlock;
  191. PLMDR_REQUEST_PACKET Drrp = (PLMDR_REQUEST_PACKET) RequestPacket;
  192. HANDLE CompletionEvent;
  193. OriginalResumeKey = Drrp->Parameters.EnumerateNames.ResumeHandle;
  194. //
  195. // If PreferedMaximumLength is MAXULONG, then we are supposed to get all
  196. // the information, regardless of size. Allocate the output buffer of a
  197. // reasonable size and try to use it. If this fails, the Redirector FSD
  198. // will say how much we need to allocate.
  199. //
  200. if (PreferedMaximumLength == MAXULONG) {
  201. OutputBufferLength = (BufferHintSize) ?
  202. BufferHintSize :
  203. INITIAL_ALLOCATION_SIZE;
  204. }
  205. else {
  206. OutputBufferLength = PreferedMaximumLength;
  207. }
  208. OutputBufferLength = ROUND_UP_COUNT(OutputBufferLength, ALIGN_WCHAR);
  209. if ((*OutputBuffer = MIDL_user_allocate(OutputBufferLength)) == NULL) {
  210. return ERROR_NOT_ENOUGH_MEMORY;
  211. }
  212. RtlZeroMemory((PVOID) *OutputBuffer, OutputBufferLength);
  213. CompletionEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  214. if (CompletionEvent == NULL) {
  215. MIDL_user_free(*OutputBuffer);
  216. *OutputBuffer = NULL;
  217. return(GetLastError());
  218. }
  219. Drrp->Parameters.EnumerateServers.EntriesRead = 0;
  220. //
  221. // Make the request of the Datagram Receiver
  222. //
  223. ntstatus = NtDeviceIoControlFile(
  224. FileHandle,
  225. CompletionEvent,
  226. NULL, // APC routine
  227. NULL, // APC context
  228. &IoStatusBlock,
  229. DeviceControlCode,
  230. Drrp,
  231. RequestPacketLength,
  232. *OutputBuffer,
  233. OutputBufferLength
  234. );
  235. if (NT_SUCCESS(ntstatus)) {
  236. //
  237. // If pending was returned, then wait until the request completes.
  238. //
  239. if (ntstatus == STATUS_PENDING) {
  240. do {
  241. ntstatus = WaitForSingleObjectEx(CompletionEvent, 0xffffffff, TRUE);
  242. } while ( ntstatus == WAIT_IO_COMPLETION );
  243. }
  244. if (NT_SUCCESS(ntstatus)) {
  245. ntstatus = IoStatusBlock.Status;
  246. }
  247. }
  248. //
  249. // Map NT status to Win error
  250. //
  251. status = NetpNtStatusToApiStatus(ntstatus);
  252. if (status == ERROR_MORE_DATA) {
  253. NetpAssert(
  254. FIELD_OFFSET(
  255. LMDR_REQUEST_PACKET,
  256. Parameters.EnumerateNames.TotalBytesNeeded
  257. ) ==
  258. FIELD_OFFSET(
  259. LMDR_REQUEST_PACKET,
  260. Parameters.EnumerateServers.TotalBytesNeeded
  261. )
  262. );
  263. NetpAssert(
  264. FIELD_OFFSET(
  265. LMDR_REQUEST_PACKET,
  266. Parameters.GetBrowserServerList.TotalBytesNeeded
  267. ) ==
  268. FIELD_OFFSET(
  269. LMDR_REQUEST_PACKET,
  270. Parameters.EnumerateServers.TotalBytesNeeded
  271. )
  272. );
  273. TotalBytesNeeded = Drrp->Parameters.EnumerateNames.TotalBytesNeeded;
  274. }
  275. if ((TotalBytesNeeded > OutputBufferLength) &&
  276. (PreferedMaximumLength == MAXULONG)) {
  277. PLMDR_REQUEST_PACKET Drrp = (PLMDR_REQUEST_PACKET) RequestPacket;
  278. //
  279. // Initial output buffer allocated was too small and we need to return
  280. // all data. First free the output buffer before allocating the
  281. // required size plus a fudge factor just in case the amount of data
  282. // grew.
  283. //
  284. MIDL_user_free(*OutputBuffer);
  285. OutputBufferLength =
  286. ROUND_UP_COUNT((TotalBytesNeeded + FUDGE_FACTOR_SIZE),
  287. ALIGN_WCHAR);
  288. if ((*OutputBuffer = MIDL_user_allocate(OutputBufferLength)) == NULL) {
  289. return ERROR_NOT_ENOUGH_MEMORY;
  290. }
  291. RtlZeroMemory((PVOID) *OutputBuffer, OutputBufferLength);
  292. NetpAssert(
  293. FIELD_OFFSET(
  294. LMDR_REQUEST_PACKET,
  295. Parameters.EnumerateNames.ResumeHandle
  296. ) ==
  297. FIELD_OFFSET(
  298. LMDR_REQUEST_PACKET,
  299. Parameters.EnumerateServers.ResumeHandle
  300. )
  301. );
  302. NetpAssert(
  303. FIELD_OFFSET(
  304. LMDR_REQUEST_PACKET,
  305. Parameters.EnumerateNames.ResumeHandle
  306. ) ==
  307. FIELD_OFFSET(
  308. LMDR_REQUEST_PACKET,
  309. Parameters.GetBrowserServerList.ResumeHandle
  310. )
  311. );
  312. Drrp->Parameters.EnumerateNames.ResumeHandle = OriginalResumeKey;
  313. Drrp->Parameters.EnumerateServers.EntriesRead = 0;
  314. //
  315. // Make the request of the Datagram Receiver
  316. //
  317. ntstatus = NtDeviceIoControlFile(
  318. FileHandle,
  319. CompletionEvent,
  320. NULL, // APC routine
  321. NULL, // APC context
  322. &IoStatusBlock,
  323. DeviceControlCode,
  324. Drrp,
  325. RequestPacketLength,
  326. *OutputBuffer,
  327. OutputBufferLength
  328. );
  329. if (NT_SUCCESS(ntstatus)) {
  330. //
  331. // If pending was returned, then wait until the request completes.
  332. //
  333. if (ntstatus == STATUS_PENDING) {
  334. do {
  335. ntstatus = WaitForSingleObjectEx(CompletionEvent, 0xffffffff, TRUE);
  336. } while ( ntstatus == WAIT_IO_COMPLETION );
  337. }
  338. if (NT_SUCCESS(ntstatus)) {
  339. ntstatus = IoStatusBlock.Status;
  340. }
  341. }
  342. status = NetpNtStatusToApiStatus(ntstatus);
  343. }
  344. //
  345. // If not successful in getting any data, or if the caller asked for
  346. // all available data with PreferedMaximumLength == MAXULONG and
  347. // our buffer overflowed, free the output buffer and set its pointer
  348. // to NULL.
  349. //
  350. if ((status != NERR_Success && status != ERROR_MORE_DATA) ||
  351. (TotalBytesNeeded == 0) ||
  352. (PreferedMaximumLength == MAXULONG && status == ERROR_MORE_DATA) ||
  353. (Drrp->Parameters.EnumerateServers.EntriesRead == 0)) {
  354. MIDL_user_free(*OutputBuffer);
  355. *OutputBuffer = NULL;
  356. //
  357. // PreferedMaximumLength == MAXULONG and buffer overflowed means
  358. // we do not have enough memory to satisfy the request.
  359. //
  360. if (status == ERROR_MORE_DATA) {
  361. status = ERROR_NOT_ENOUGH_MEMORY;
  362. }
  363. }
  364. CloseHandle(CompletionEvent);
  365. return status;
  366. UNREFERENCED_PARAMETER(Information);
  367. }