2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
9 /* AFSIFS portions copyright (c) 2005
10 * the regents of the university of michigan
13 * permission is granted to use, copy, create derivative works and
14 * redistribute this software and such derivative works for any purpose,
15 * so long as the name of the university of michigan is not used in
16 * any advertising or publicity pertaining to the use or distribution
17 * of this software without specific, written prior authorization. if
18 * the above copyright notice or any other identification of the
19 * university of michigan is included in any copy of any portion of
20 * this software, then the disclaimer below must also be included.
22 * this software is provided as is, without representation from the
23 * university of michigan as to its fitness for any purpose, and without
24 * warranty by the university of michigan of any kind, either express
25 * or implied, including without limitation the implied warranties of
26 * merchantability and fitness for a particular purpose. the regents
27 * of the university of michigan shall not be liable for any damages,
28 * including special, indirect, incidental, or consequential damages,
29 * with respect to any claim arising out or in connection with the use
30 * of the software, even if it has been or is hereafter advised of the
31 * possibility of such damages.
34 #include <afsconfig.h>
35 #include <afs/param.h>
49 #define SECURITY_WIN32
60 #include <cm_scache.h>
66 #include <pioctl_nt.h>
67 #include <WINNT/afsreg.h>
68 #include <lanahelper.h>
69 #include <../WINNT/afsrdr/kif.h>
71 #include <loadfuncs-krb5.h>
74 static char AFSConfigKeyName[] = AFSREG_CLT_SVC_PARAM_SUBKEY;
76 #define FS_IOCTLREQUEST_MAXSIZE 8192
77 /* big structure for representing and storing an IOCTL request */
78 typedef struct fs_ioctlRequest {
79 char *mp; /* marshalling/unmarshalling ptr */
80 long nbytes; /* bytes received (when unmarshalling) */
81 char data[FS_IOCTLREQUEST_MAXSIZE]; /* data we're marshalling */
85 CMtoUNIXerror(int cm_code)
88 case CM_ERROR_TIMEDOUT:
90 case CM_ERROR_NOACCESS:
92 case CM_ERROR_NOSUCHFILE:
100 case CM_ERROR_CROSSDEVLINK:
102 case CM_ERROR_NOTDIR:
106 case CM_ERROR_READONLY:
108 case CM_ERROR_WOULDBLOCK:
110 case CM_ERROR_NOSUCHCELL:
111 return ESRCH; /* hack */
112 case CM_ERROR_NOSUCHVOLUME:
113 return EPIPE; /* hack */
114 case CM_ERROR_NOMORETOKENS:
115 return EDOM; /* hack */
116 case CM_ERROR_TOOMANYBUFS:
117 return EFBIG; /* hack */
119 if (cm_code > 0 && cm_code < EILSEQ)
127 InitFSRequest(fs_ioctlRequest_t * rp)
137 static BOOL debug = 0;
142 if (RegOpenKey (HKEY_LOCAL_MACHINE,
143 TEXT("Software\\OpenAFS\\Client"), &hk) == 0)
145 DWORD dwSize = sizeof(BOOL);
146 DWORD dwType = REG_DWORD;
147 RegQueryValueEx (hk, TEXT("IoctlDebug"), NULL, &dwType, (PBYTE)&debug, &dwSize);
159 LPSTR lpszMachineName,
160 LPSTR lpszServiceName,
161 DWORD *lpdwCurrentState)
164 SC_HANDLE schSCManager = NULL;
165 SC_HANDLE schService = NULL;
166 DWORD fdwDesiredAccess = 0;
167 SERVICE_STATUS ssServiceStatus = {0};
170 *lpdwCurrentState = 0;
172 fdwDesiredAccess = GENERIC_READ;
174 schSCManager = OpenSCManager(lpszMachineName,
178 if(schSCManager == NULL)
184 schService = OpenService(schSCManager,
188 if(schService == NULL)
194 fRet = QueryServiceStatus(schService,
203 *lpdwCurrentState = ssServiceStatus.dwCurrentState;
207 CloseServiceHandle(schService);
208 CloseServiceHandle(schSCManager);
214 DECL_FUNC_PTR(krb5_cc_default_name);
215 DECL_FUNC_PTR(krb5_cc_set_default_name);
216 DECL_FUNC_PTR(krb5_get_default_config_files);
217 DECL_FUNC_PTR(krb5_free_config_files);
218 DECL_FUNC_PTR(krb5_free_context);
219 DECL_FUNC_PTR(krb5_get_default_realm);
220 DECL_FUNC_PTR(krb5_free_default_realm);
221 DECL_FUNC_PTR(krb5_init_context);
222 DECL_FUNC_PTR(krb5_cc_default);
223 DECL_FUNC_PTR(krb5_parse_name);
224 DECL_FUNC_PTR(krb5_free_principal);
225 DECL_FUNC_PTR(krb5_cc_close);
226 DECL_FUNC_PTR(krb5_cc_get_principal);
227 DECL_FUNC_PTR(krb5_build_principal);
228 DECL_FUNC_PTR(krb5_c_random_make_octets);
229 DECL_FUNC_PTR(krb5_get_init_creds_password);
230 DECL_FUNC_PTR(krb5_free_cred_contents);
231 DECL_FUNC_PTR(krb5_cc_resolve);
232 DECL_FUNC_PTR(krb5_unparse_name);
233 DECL_FUNC_PTR(krb5_free_unparsed_name);
235 FUNC_INFO krb5_fi[] = {
236 MAKE_FUNC_INFO(krb5_cc_default_name),
237 MAKE_FUNC_INFO(krb5_cc_set_default_name),
238 MAKE_FUNC_INFO(krb5_get_default_config_files),
239 MAKE_FUNC_INFO(krb5_free_config_files),
240 MAKE_FUNC_INFO(krb5_free_context),
241 MAKE_FUNC_INFO(krb5_get_default_realm),
242 MAKE_FUNC_INFO(krb5_free_default_realm),
243 MAKE_FUNC_INFO(krb5_init_context),
244 MAKE_FUNC_INFO(krb5_cc_default),
245 MAKE_FUNC_INFO(krb5_parse_name),
246 MAKE_FUNC_INFO(krb5_free_principal),
247 MAKE_FUNC_INFO(krb5_cc_close),
248 MAKE_FUNC_INFO(krb5_cc_get_principal),
249 MAKE_FUNC_INFO(krb5_build_principal),
250 MAKE_FUNC_INFO(krb5_c_random_make_octets),
251 MAKE_FUNC_INFO(krb5_get_init_creds_password),
252 MAKE_FUNC_INFO(krb5_free_cred_contents),
253 MAKE_FUNC_INFO(krb5_cc_resolve),
254 MAKE_FUNC_INFO(krb5_unparse_name),
255 MAKE_FUNC_INFO(krb5_free_unparsed_name),
261 const char* dll_name,
263 HINSTANCE* ph, // [out, optional] - DLL handle
264 int* pindex, // [out, optional] - index of last func loaded (-1 if none)
265 int cleanup, // cleanup function pointers and unload on error
266 int go_on, // continue loading even if some functions cannot be loaded
267 int silent // do not pop-up a system dialog if DLL cannot be loaded
276 if (pindex) *pindex = -1;
278 for (n = 0; fi[n].func_ptr_var; n++)
279 *(fi[n].func_ptr_var) = 0;
282 em = SetErrorMode(SEM_FAILCRITICALERRORS);
283 h = LoadLibrary(dll_name);
291 for (i = 0; (go_on || !error) && (i < n); i++)
293 void* p = (void*)GetProcAddress(h, fi[i].func_name);
299 *(fi[i].func_ptr_var) = p;
302 if (pindex) *pindex = last_i;
303 if (error && cleanup && !go_on) {
304 for (i = 0; i < n; i++) {
305 *(fi[i].func_ptr_var) = 0;
314 #if defined(_IA64_) || defined(_AMD64_)
315 #define KERB5DLL "krb5_64.dll"
317 #define KERB5DLL "krb5_32.dll"
322 static HINSTANCE hKrb5DLL = 0;
327 hKrb5DLL = LoadLibrary(KERB5DLL);
329 if (!LoadFuncs(KERB5DLL, krb5_fi, 0, 0, 1, 0, 0))
331 FreeLibrary(hKrb5DLL);
341 GetLSAPrincipalName(char * szUser, DWORD *dwSize)
343 krb5_context ctx = 0;
344 krb5_error_code code;
345 krb5_ccache mslsa_ccache=0;
346 krb5_principal princ = 0;
350 if (!IsKrb5Available())
353 if (code = pkrb5_init_context(&ctx))
356 if (code = pkrb5_cc_resolve(ctx, "MSLSA:", &mslsa_ccache))
359 if (code = pkrb5_cc_get_principal(ctx, mslsa_ccache, &princ))
362 if (code = pkrb5_unparse_name(ctx, princ, &pname))
365 if ( strlen(pname) < *dwSize ) {
366 strncpy(szUser, pname, *dwSize);
367 szUser[*dwSize-1] = '\0';
370 *dwSize = (DWORD)strlen(pname);
374 pkrb5_free_unparsed_name(ctx, pname);
377 pkrb5_free_principal(ctx, princ);
380 pkrb5_cc_close(ctx, mslsa_ccache);
383 pkrb5_free_context(ctx);
388 GetIoctlHandle(char *fileNamep, HANDLE * handlep)
392 char netbiosName[MAX_NB_NAME_LENGTH];
393 DWORD CurrentState = 0;
394 char HostName[64] = "";
396 char tbuffer[256]="";
399 char szUser[128] = "";
400 char szClient[MAX_PATH] = "";
401 char szPath[MAX_PATH] = "";
404 DWORD ioctlDebug = IoctlDebug();
406 DWORD dwSize = sizeof(szUser);
409 memset(HostName, '\0', sizeof(HostName));
410 gethostname(HostName, sizeof(HostName));
411 if (GetServiceStatus(HostName, TEXT("TransarcAFSDaemon"), &CurrentState) == NOERROR &&
412 CurrentState != SERVICE_RUNNING)
416 drivep = strchr(fileNamep, ':');
417 if (drivep && (drivep - fileNamep) >= 1) {
418 tbuffer[0] = *(drivep - 1);
420 strcpy(tbuffer + 2, SMB_IOCTL_FILENAME);
421 } else if (fileNamep[0] == fileNamep[1] &&
422 (fileNamep[0] == '\\' || fileNamep[0] == '/'))
424 int count = 0, i = 0;
426 while (count < 4 && fileNamep[i]) {
427 tbuffer[i] = fileNamep[i];
428 if ( tbuffer[i] == '\\' ||
433 if (fileNamep[i] == 0)
436 strcat(tbuffer, SMB_IOCTL_FILENAME);
440 GetCurrentDirectory(sizeof(curdir), curdir);
441 if ( curdir[1] == ':' ) {
442 tbuffer[0] = curdir[0];
444 strcpy(tbuffer + 2, SMB_IOCTL_FILENAME);
445 } else if (curdir[0] == curdir[1] &&
446 (curdir[0] == '\\' || curdir[0] == '/'))
448 int count = 0, i = 0;
450 while (count < 4 && curdir[i]) {
451 tbuffer[i] = curdir[i];
452 if ( tbuffer[i] == '\\' ||
460 strcat(tbuffer, SMB_IOCTL_FILENAME_NOSLASH);
465 /* No file name starting with drive colon specified, use UNC name */
466 lana_GetNetbiosName(netbiosName,LANA_NETBIOS_NAME_FULL);
467 sprintf(tbuffer,"\\\\%s\\all%s",netbiosName,SMB_IOCTL_FILENAME);
470 sprintf(tbuffer,"\\\\.\\afscom\\ioctl");
474 /* now open the file */
475 fh = CreateFile(tbuffer, GENERIC_READ | GENERIC_WRITE,
476 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
477 FILE_FLAG_WRITE_THROUGH, NULL);
482 if (fh == INVALID_HANDLE_VALUE) {
487 if (fh == INVALID_HANDLE_VALUE) {
490 gle = GetLastError();
491 if (gle && ioctlDebug ) {
494 if ( FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
497 MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),
503 fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%X\r\n\t[%s]\r\n",
508 lana_GetNetbiosName(szClient, LANA_NETBIOS_NAME_FULL);
510 if (RegOpenKey (HKEY_CURRENT_USER,
511 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"), &hk) == 0)
513 DWORD dwType = REG_SZ;
514 RegQueryValueEx (hk, TEXT("Logon User Name"), NULL, &dwType, (PBYTE)szUser, &dwSize);
520 fprintf(stderr, "pioctl Explorer logon user: [%s]\r\n",szUser);
522 sprintf(szPath, "\\\\%s", szClient);
523 memset (&nr, 0x00, sizeof(NETRESOURCE));
524 nr.dwType=RESOURCETYPE_DISK;
526 nr.lpRemoteName=szPath;
527 res = WNetAddConnection2(&nr,NULL,szUser,0);
530 fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
536 sprintf(szPath, "\\\\%s\\all", szClient);
537 res = WNetAddConnection2(&nr,NULL,szUser,0);
540 fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
547 goto try_lsa_principal;
549 fh = CreateFile(tbuffer, GENERIC_READ | GENERIC_WRITE,
550 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
551 FILE_FLAG_WRITE_THROUGH, NULL);
553 if (fh == INVALID_HANDLE_VALUE) {
554 gle = GetLastError();
555 if (gle && ioctlDebug ) {
558 if ( FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
561 MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),
567 fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%X\r\n\t[%s]\r\n",
576 if (fh == INVALID_HANDLE_VALUE) {
579 dwSize = sizeof(szUser);
580 if (GetLSAPrincipalName(szUser, &dwSize)) {
582 fprintf(stderr, "pioctl LSA Principal logon user: [%s]\r\n",szUser);
584 sprintf(szPath, "\\\\%s", szClient);
585 memset (&nr, 0x00, sizeof(NETRESOURCE));
586 nr.dwType=RESOURCETYPE_DISK;
588 nr.lpRemoteName=szPath;
589 res = WNetAddConnection2(&nr,NULL,szUser,0);
592 fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
598 sprintf(szPath, "\\\\%s\\all", szClient);
599 res = WNetAddConnection2(&nr,NULL,szUser,0);
602 fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
611 fh = CreateFile(tbuffer, GENERIC_READ | GENERIC_WRITE,
612 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
613 FILE_FLAG_WRITE_THROUGH, NULL);
615 if (fh == INVALID_HANDLE_VALUE) {
616 gle = GetLastError();
617 if (gle && ioctlDebug ) {
620 if ( FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
623 MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),
629 fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%X\r\n\t[%s]\r\n",
638 if ( fh == INVALID_HANDLE_VALUE ) {
639 dwSize = sizeof(szUser);
640 if (GetUserNameEx(NameSamCompatible, szUser, &dwSize)) {
642 fprintf(stderr, "pioctl SamCompatible logon user: [%s]\r\n",szUser);
644 sprintf(szPath, "\\\\%s", szClient);
645 memset (&nr, 0x00, sizeof(NETRESOURCE));
646 nr.dwType=RESOURCETYPE_DISK;
648 nr.lpRemoteName=szPath;
649 res = WNetAddConnection2(&nr,NULL,szUser,0);
652 fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
657 sprintf(szPath, "\\\\%s\\all", szClient);
658 res = WNetAddConnection2(&nr,NULL,szUser,0);
661 fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
667 fh = CreateFile(tbuffer, GENERIC_READ | GENERIC_WRITE,
668 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
669 FILE_FLAG_WRITE_THROUGH, NULL);
671 if (fh == INVALID_HANDLE_VALUE) {
672 gle = GetLastError();
673 if (gle && ioctlDebug ) {
676 if ( FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
679 MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),
685 fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%X\r\n\t[%s]\r\n",
692 fprintf(stderr, "GetUserNameEx(NameSamCompatible) failed: 0x%X\r\n", GetLastError());
697 /* return fh and success code */
703 Transceive(HANDLE handle, fs_ioctlRequest_t * reqp)
712 rcount = (long)(reqp->mp - reqp->data);
715 fprintf(stderr, "pioctl Transceive rcount <= 0: %d\r\n",rcount);
716 return EINVAL; /* not supposed to happen */
720 if (!WriteFile(handle, reqp->data, rcount, &ioCount, NULL)) {
721 /* failed to write */
722 gle = GetLastError();
725 fprintf(stderr, "pioctl Transceive WriteFile failed: 0x%X\r\n",gle);
729 if (!ReadFile(handle, reqp->data, sizeof(reqp->data), &ioCount, NULL)) {
731 gle = GetLastError();
734 fprintf(stderr, "pioctl Transceive ReadFile failed: 0x%X\r\n",gle);
738 /* ioctl completes as one operation, so copy input to a new buffer, and use as output buffer */
739 data = malloc(rcount);
740 memcpy(data, reqp->data, rcount);
741 if (!DeviceIoControl(handle, IOCTL_AFSRDR_IOCTL, data, rcount, reqp->data, sizeof(reqp->data), &ioCount, NULL))
744 return GetLastError();
749 reqp->nbytes = ioCount; /* set # of bytes available */
750 reqp->mp = reqp->data; /* restart marshalling */
757 MarshallLong(fs_ioctlRequest_t * reqp, long val)
759 memcpy(reqp->mp, &val, 4);
765 UnmarshallLong(fs_ioctlRequest_t * reqp, long *valp)
767 /* not enough data left */
768 if (reqp->nbytes < 4) {
770 fprintf(stderr, "pioctl UnmarshallLong reqp->nbytes < 4: %d\r\n",
775 memcpy(valp, reqp->mp, 4);
781 /* includes marshalling NULL pointer as a null (0 length) string */
783 MarshallString(fs_ioctlRequest_t * reqp, char *stringp)
788 count = (int)strlen(stringp) + 1;/* space required including null */
792 /* watch for buffer overflow */
793 if ((reqp->mp - reqp->data) + count > sizeof(reqp->data)) {
795 fprintf(stderr, "pioctl MarshallString buffer overflow\r\n");
800 memcpy(reqp->mp, stringp, count);
807 /* take a path with a drive letter, possibly relative, and return a full path
808 * without the drive letter. This is the full path relative to the working
809 * dir for that drive letter. The input and output paths can be the same.
812 fs_GetFullPath(char *pathp, char *outPathp, long outSize)
824 unsigned long length;
830 return CM_ERROR_NOSUCHPATH;
832 rootDir = CreateFile(pathp, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
833 if (rootDir == INVALID_HANDLE_VALUE)
834 return CM_ERROR_NOSUCHPATH;
836 wpath = (wchar_t *)tpath;
838 if (!DeviceIoControl(rootDir, IOCTL_AFSRDR_GET_PATH, NULL, 0, wpath, 1000, &length, NULL))
840 CloseHandle(rootDir);
841 return CM_ERROR_NOSUCHPATH;
843 CloseHandle(rootDir);
845 code = WideCharToMultiByte(CP_UTF8, 0/*WC_NO_BEST_FIT_CHARS*/, wpath, length/sizeof(wchar_t), outPathp, outSize/sizeof(wchar_t), NULL, NULL);
849 if (pathp[0] != 0 && pathp[1] == ':') {
850 /* there's a drive letter there */
858 if ( firstp[0] == '\\' && firstp[1] == '\\' ||
859 firstp[0] == '/' && firstp[1] == '/') {
860 /* UNC path - strip off the server and sharename */
862 for ( i=2,count=2; count < 4 && firstp[i]; i++ ) {
863 if ( firstp[i] == '\\' || firstp[i] == '/' ) {
867 if ( firstp[i] == 0 ) {
868 strcpy(outPathp,"\\");
870 strcpy(outPathp,&firstp[--i]);
872 for (p=outPathp ;*p; p++) {
877 } else if (firstp[0] == '\\' || firstp[0] == '/') {
878 /* already an absolute pathname, just copy it back */
879 strcpy(outPathp, firstp);
880 for (p=outPathp ;*p; p++) {
887 GetCurrentDirectory(sizeof(origPath), origPath);
890 if (pathHasDrive && (*pathp & ~0x20) != (origPath[0] & ~0x20)) {
891 /* a drive has been specified and it isn't our current drive.
892 * to get path, switch to it first. Must case-fold drive letters
893 * for user convenience.
899 if (!SetCurrentDirectory(newPath)) {
900 code = GetLastError();
903 fprintf(stderr, "pioctl fs_GetFullPath SetCurrentDirectory(%s) failed: 0x%X\r\n",
909 /* now get the absolute path to the current wdir in this drive */
910 GetCurrentDirectory(sizeof(tpath), tpath);
912 strcpy(outPathp, tpath + 2); /* skip drive letter */
913 else if ( tpath[0] == '\\' && tpath[1] == '\\'||
914 tpath[0] == '/' && tpath[1] == '/') {
915 /* UNC path - strip off the server and sharename */
917 for ( i=2,count=2; count < 4 && tpath[i]; i++ ) {
918 if ( tpath[i] == '\\' || tpath[i] == '/' ) {
922 if ( tpath[i] == 0 ) {
923 strcpy(outPathp,"\\");
925 strcpy(outPathp,&tpath[--i]);
928 /* this should never happen */
929 strcpy(outPathp, tpath);
932 /* if there is a non-null name after the drive, append it */
934 int len = (int)strlen(outPathp);
935 if (outPathp[len-1] != '\\' && outPathp[len-1] != '/')
936 strcat(outPathp, "\\");
937 strcat(outPathp, firstp);
940 /* finally, if necessary, switch back to our home drive letter */
942 SetCurrentDirectory(origPath);
945 for (p=outPathp ;*p; p++) {
954 pioctl(char *pathp, long opcode, struct ViceIoctl *blobp, int follow)
956 fs_ioctlRequest_t preq;
962 code = GetIoctlHandle(pathp, &reqHandle);
971 /* init the request structure */
972 InitFSRequest(&preq);
974 /* marshall the opcode, the path name and the input parameters */
975 MarshallLong(&preq, opcode);
976 /* when marshalling the path, remove the drive letter, since we already
977 * used the drive letter to find the AFS daemon; we don't need it any more.
978 * Eventually we'll expand relative path names here, too, since again, only
979 * we understand those.
982 code = fs_GetFullPath(pathp, fullPath, sizeof(fullPath));
984 CloseHandle(reqHandle);
989 strcpy(fullPath, "");
992 MarshallString(&preq, fullPath);
993 if (blobp->in_size) {
994 memcpy(preq.mp, blobp->in, blobp->in_size);
995 preq.mp += blobp->in_size;
998 /* now make the call */
999 code = Transceive(reqHandle, &preq);
1001 CloseHandle(reqHandle);
1005 /* now unmarshall the return value */
1006 if (UnmarshallLong(&preq, &temp) != 0) {
1007 CloseHandle(reqHandle);
1012 CloseHandle(reqHandle);
1013 errno = CMtoUNIXerror(temp);
1015 fprintf(stderr, "pioctl temp != 0: 0x%X\r\n",temp);
1019 /* otherwise, unmarshall the output parameters */
1020 if (blobp->out_size) {
1021 temp = blobp->out_size;
1022 if (preq.nbytes < temp)
1024 memcpy(blobp->out, preq.mp, temp);
1025 blobp->out_size = temp;
1028 /* and return success */
1029 CloseHandle(reqHandle);