windows-nt/Source/XPSP1/NT/ds/adsi/ndsext/exe/client32.cpp
2020-09-26 16:20:57 +08:00

791 lines
23 KiB
C++

#include "main.h"
#include <nwcalls.h>
#include <nwnet.h>
#include <nwlocale.h>
#include "typedef.h"
DWORD LoadNetwareDLLs();
PF_NWCallsInit pfNWCallsInit = NULL;
PF_NWFreeUnicodeTables pfNWFreeUnicodeTables= NULL;
PF_NWInitUnicodeTables pfNWInitUnicodeTables= NULL;
PF_NWLlocaleconv pfNWLlocaleconv= NULL;
PF_NWDSFreeContext pfNWDSFreeContext= NULL;
PF_NWDSFreeBuf pfNWDSFreeBuf= NULL;
PF_NWDSLogout pfNWDSLogout= NULL;
PF_NWDSGetAttrDef pfNWDSGetAttrDef= NULL;
PF_NWDSGetAttrCount pfNWDSGetAttrCount= NULL;
PF_NWDSReadAttrDef pfNWDSReadAttrDef= NULL;
PF_NWDSPutAttrName pfNWDSPutAttrName= NULL;
PF_NWDSInitBuf pfNWDSInitBuf= NULL;
PF_NWDSAllocBuf pfNWDSAllocBuf= NULL;
PF_NWDSLogin pfNWDSLogin= NULL;
PF_NWDSSetContext pfNWDSSetContext= NULL;
PF_NWDSGetContext pfNWDSGetContext= NULL;
PF_NWIsDSAuthenticated pfNWIsDSAuthenticated= NULL;
PF_NWDSCreateContext pfNWDSCreateContext= NULL;
PF_NWDSModifyClassDef pfNWDSModifyClassDef = NULL;
PF_NWDSDefineAttr pfNWDSDefineAttr = NULL;
HINSTANCE calwin32LibraryHandle = NULL;
HINSTANCE locwin32LibraryHandle = NULL;
HINSTANCE netwin32LibraryHandle = NULL;
DWORD Client32CheckSchemaExtension(
PWSTR szServer,
PWSTR szContext,
PWSTR szUser,
PWSTR szPasswd,
BOOL *pfExtended
)
{
NWDSContextHandle context = NULL;
pBuf_T pInBuf = NULL;
pBuf_T pOutBuf = NULL;
BOOL fFreeUnicodeTable = FALSE;
BOOL fLoggedIn= FALSE;
BOOL fLogout = TRUE;
nint32 lIterationHandle;
Attr_Info_T attrInfo;
NWDSCCODE ccode;
nuint32 luTotalAttr;
nstr8 strAttrName[MAX_SCHEMA_NAME_CHARS];
nuint i;
LCONV lConvInfo;
nstr8 treeName[MAX_DN_CHARS+1];
nstr8 strName[MAX_DN_CHARS+1];
BOOL fSchemaExtended = FALSE;
DWORD WinError;
PSTR pszServer = NULL;
PSTR pszContext = NULL;
PSTR pszUser = NULL;
PSTR pszPasswd = NULL;
//
// We only check server and extended because they are the only must-have
// parameters
//
if (!(szServer && pfExtended)) {
ERR(("Invalid parameters.\n"));
WinError = ERROR_INVALID_PARAMETER;
BAIL();
}
//
// Basic initialization
//
WinError = LoadNetwareDLLs();
if (WinError) {
BAIL();
}
ccode = pfNWCallsInit(NULL,NULL);
if (ccode) {
ERR(("NWCallsInit returned %X\n", ccode));
BAIL();
}
pfNWLlocaleconv(&lConvInfo);
ccode = pfNWInitUnicodeTables(lConvInfo.country_id,
lConvInfo.code_page);
if (ccode) {
ERR(("NWInitUnicodeTables returned %X\n", ccode));
BAIL();
}
fFreeUnicodeTable = TRUE;
context = pfNWDSCreateContext();
if (context == (NWDSContextHandle)ERR_CONTEXT_CREATION) {
ERR(("NWDSCreateContext failed\n"));
BAIL();
}
pszServer = AllocateAnsiString(szServer);
if (pszServer == NULL) {
WinError = ERROR_NO_SYSTEM_RESOURCES;
BAIL();
}
if (szContext == NULL) {
goto doit;
}
pszContext = AllocateAnsiString(szContext);
if (pszContext == NULL) {
WinError = ERROR_NO_SYSTEM_RESOURCES;
BAIL();
}
pszUser = AllocateAnsiString(szUser);
if (pszUser == NULL) {
WinError = ERROR_NO_SYSTEM_RESOURCES;
BAIL();
}
pszPasswd = AllocateAnsiString(szPasswd);
if (pszPasswd == NULL) {
WinError = ERROR_NO_SYSTEM_RESOURCES;
BAIL();
}
if(!pfNWIsDSAuthenticated()) {
DEBUGOUT(("The system is not authenticated.\n"));
}
else {
DEBUGOUT(("The system has been authenticated already\n"));
//
// Get Current tree's name
//
ccode = pfNWDSGetContext(context, DCK_TREE_NAME, &treeName);
if(ccode) {
ERR(("Get context returned %X\n", ccode));
BAIL();
}
DEBUGOUT(("Current Tree is %s.\n",treeName));
//
// Get current context's name
//
ccode = pfNWDSGetContext(context, DCK_NAME_CONTEXT, &strName);
if(ccode) {
ERR(("\nGet context returned %X", ccode));
BAIL();
}
DEBUGOUT(("Current Context is %s.\n",strName));
//
// If the current tree and context is the same as the desired tree
// and context, we do not need to logout. Because that would blow out
// the connection.
//
if ((_stricmp(treeName,pszServer) == 0) &&
(_stricmp(strName,pszContext) == 0)) {
DEBUGOUT(("Will not logout.\n",strName));
fLogout = FALSE;
}
}
//
// Set context to another tree
//
ccode = pfNWDSSetContext(context,
DCK_TREE_NAME,
pszServer
);
if(ccode) {
ERR(("\nSet context returned %X", ccode));
BAIL();
}
//
// Set context to another context
//
ccode = pfNWDSSetContext(
context,
DCK_NAME_CONTEXT,
pszContext
);
if(ccode) {
ERR(("\nSet context returned %X", ccode));
BAIL();
}
//
// Get Current tree's name
//
ccode = pfNWDSGetContext(context, DCK_TREE_NAME, &treeName);
if(ccode) {
ERR(("\nGet context returned %X", ccode));
BAIL();
}
DEBUGOUT(("Current tree is %s.\n",treeName));
ccode = pfNWDSGetContext(context, DCK_NAME_CONTEXT, &strName);
if(ccode) {
ERR(("\nGet context returned %X", ccode));
BAIL();
}
DEBUGOUT(("Current conext is now %s.\n",strName));
//
// Logging into new tree
//
DEBUGOUT(("Logging in...\n"));
ccode = pfNWDSLogin(context, 0, pszUser, pszPasswd, 0);
if(ccode) {
ERR(("\nNWDSLogin returned %X\n", ccode));
BAIL();
}
else {
fLoggedIn = TRUE;
DEBUGOUT(("Logged in successfully.\n"));
}
doit:
if(pfNWIsDSAuthenticated())
DEBUGOUT(("The system has been authenticated already\n"));
else
DEBUGOUT(("The system is not authenticated.\n"));
ccode = pfNWDSAllocBuf(DEFAULT_MESSAGE_LEN, &pInBuf);
if(ccode) {
ERR(("\nNWDSAllocBuf returned %X", ccode));
BAIL();
}
ccode = pfNWDSAllocBuf(DEFAULT_MESSAGE_LEN, &pOutBuf);
if(ccode) {
ERR(("\nNWDSAllocBuf returned %X", ccode));
BAIL();
}
ccode = pfNWDSInitBuf(context, DSV_READ_ATTR_DEF, pInBuf);
if(ccode) {
ERR(("\nNWDSInitBuf returned %X", ccode));
BAIL();
}
ccode = pfNWDSPutAttrName(context, pInBuf, (PSTR)g_szAttributeNameA);
if(ccode) {
ERR(("\nNWDSPutAttrName returned %X", ccode));
BAIL();
}
lIterationHandle = NO_MORE_ITERATIONS;
ccode = pfNWDSReadAttrDef(context,
DS_ATTR_DEFS, /* infoType, attribute definitions */
FALSE, /* allAttrs = false, passing in one */
pInBuf, /* through this buffer (strAttrNames) */
&lIterationHandle,
pOutBuf);
if (ccode == ERR_NO_SUCH_ATTRIBUTE) {
ccode = 0;
BAIL();
}
else if (ccode) {
ERR(("\nNWDSReadAttrDef returned %X", ccode));
BAIL();
}
ccode = pfNWDSGetAttrCount(context, pOutBuf, &luTotalAttr);
if(ccode) {
ERR(("\nNWDSGetAttrCount returned %X", ccode));
BAIL();
}
if (luTotalAttr == 1) {
ccode = pfNWDSGetAttrDef(context, pOutBuf, strAttrName, &attrInfo);
if(ccode) {
ERR(("\nNWDSGetAttrCount returned %X", ccode));
BAIL();
}
if (strcmp(strAttrName,(PSTR)g_szAttributeNameA) == 0) {
fSchemaExtended = TRUE;
}
DEBUGOUT(("Successfully retrieved information off Client32.\n"));
}
error:
if (fLogout & fLoggedIn) {
DEBUGOUT(("We are logging out.\n",strName));
pfNWDSLogout(context);
}
if (pInBuf)
pfNWDSFreeBuf(pInBuf);
if (pOutBuf)
pfNWDSFreeBuf(pOutBuf);
if (context)
pfNWDSFreeContext(context);
if (fFreeUnicodeTable)
pfNWFreeUnicodeTables();
if (pszServer)
MemFree(pszServer);
if (pszContext)
MemFree(pszContext);
if (pszUser)
MemFree(pszUser);
if (pszPasswd)
MemFree(pszPasswd);
*pfExtended = fSchemaExtended;
if (WinError == 0 && (ccode != 0)) {
WinError = ERROR_EXTENDED_ERROR;
SelectivePrint(MSG_NETWARE_ERROR,ccode);
}
return WinError;
}
DWORD Client32ExtendSchema(
PWSTR szServer,
PWSTR szContext,
PWSTR szUser,
PWSTR szPasswd
)
{
NWDSContextHandle context = NULL;
pBuf_T pInBuf = NULL;
pBuf_T pOutBuf = NULL;
BOOL fFreeUnicodeTable = FALSE;
BOOL fLoggedIn= FALSE;
BOOL fLogout = TRUE;
NWDSCCODE ccode;
nstr8 strAttrName[MAX_SCHEMA_NAME_CHARS];
nuint i;
LCONV lConvInfo;
DWORD dwSyntaxId;
DWORD dwMinValue = 0;
DWORD dwMaxValue = -1;
Asn1ID_T *pasn1ID;
Attr_Info_T AttrInfo;
nstr8 treeName[MAX_DN_CHARS+1];
nstr8 strName[MAX_DN_CHARS+1];
DWORD WinError;
PSTR pszServer = NULL;
PSTR pszContext = NULL;
PSTR pszUser = NULL;
PSTR pszPasswd = NULL;
//
// We only check server and extended because they are the only must-have
// parameters
//
if (!(szServer)) {
ERR(("Invalid parameters.\n"));
WinError = ERROR_INVALID_PARAMETER;
BAIL();
}
WinError = LoadNetwareDLLs();
if (WinError) {
BAIL();
}
ccode = pfNWCallsInit(NULL,NULL);
if (ccode) {
ERR(("NWCallsInit returned %X\n", ccode));
BAIL();
}
pfNWLlocaleconv(&lConvInfo);
ccode = pfNWInitUnicodeTables(lConvInfo.country_id,
lConvInfo.code_page);
if (ccode) {
ERR(("NWInitUnicodeTables returned %X\n", ccode));
BAIL();
}
fFreeUnicodeTable = TRUE;
context = pfNWDSCreateContext();
if (context == (NWDSContextHandle)ERR_CONTEXT_CREATION) {
ERR(("NWDSCreateContext failed\n"));
BAIL();
}
pszServer = AllocateAnsiString(szServer);
if (pszServer == NULL) {
WinError = ERROR_NO_SYSTEM_RESOURCES;
BAIL();
}
if (szContext == NULL) {
goto extendnow;
}
pszContext = AllocateAnsiString(szContext);
if (pszContext == NULL) {
WinError = ERROR_NO_SYSTEM_RESOURCES;
BAIL();
}
pszUser = AllocateAnsiString(szUser);
if (pszUser == NULL) {
WinError = ERROR_NO_SYSTEM_RESOURCES;
BAIL();
}
pszPasswd = AllocateAnsiString(szPasswd);
if (pszPasswd == NULL) {
WinError = ERROR_NO_SYSTEM_RESOURCES;
BAIL();
}
if(!pfNWIsDSAuthenticated()) {
DEBUGOUT(("The system is not authenticated.\n"));
}
else {
DEBUGOUT(("The system has been authenticated already\n"));
//
// Get Current tree's name
//
ccode = pfNWDSGetContext(context, DCK_TREE_NAME, &treeName);
if(ccode) {
ERR(("Get context returned %X\n", ccode));
BAIL();
}
DEBUGOUT(("Current Tree is %s.\n",treeName));
//
// Get current context's name
//
ccode = pfNWDSGetContext(context, DCK_NAME_CONTEXT, &strName);
if(ccode) {
ERR(("\nGet context returned %X", ccode));
BAIL();
}
DEBUGOUT(("Current Context is %s.\n",strName));
//
// If the current tree and context is the same as the desired tree
// and context, we do not need to logout. Because that would blow out
// the connection.
//
if ((_stricmp(treeName,pszServer) == 0) &&
(_stricmp(strName,pszContext) == 0)) {
DEBUGOUT(("Will not logout.\n",strName));
fLogout = FALSE;
}
}
//
// Set context to another tree
//
ccode = pfNWDSSetContext(context,
DCK_TREE_NAME,
pszServer
);
if(ccode) {
ERR(("\nSet context returned %X", ccode));
BAIL();
}
//
// Set context to another context
//
ccode = pfNWDSSetContext(
context,
DCK_NAME_CONTEXT,
pszContext
);
if(ccode) {
ERR(("\nSet context returned %X", ccode));
BAIL();
}
//
// Get Current tree's name
//
ccode = pfNWDSGetContext(context, DCK_TREE_NAME, &treeName);
if(ccode) {
ERR(("\nGet context returned %X", ccode));
BAIL();
}
DEBUGOUT(("Current tree is %s.\n",treeName));
ccode = pfNWDSGetContext(context, DCK_NAME_CONTEXT, &strName);
if(ccode) {
ERR(("\nGet context returned %X", ccode));
BAIL();
}
DEBUGOUT(("Current conext is now %s.\n",strName));
//
// Logging into new tree
//
DEBUGOUT(("Logging in...\n"));
ccode = pfNWDSLogin(context, 0, pszUser, pszPasswd, 0);
if(ccode) {
ERR(("\nNWDSLogin returned %X\n", ccode));
BAIL();
}
else {
fLoggedIn = TRUE;
DEBUGOUT(("Logged in successfully.\n"));
}
extendnow:
if(pfNWIsDSAuthenticated())
DEBUGOUT(("The system has been authenticated already\n"));
else
DEBUGOUT(("The system is not authenticated.\n"));
AttrInfo.attrFlags = DS_SINGLE_VALUED_ATTR;
AttrInfo.attrSyntaxID = SYN_OCTET_STRING;
AttrInfo.attrLower = dwMinValue;
AttrInfo.attrUpper = dwMaxValue;
pasn1ID = &(AttrInfo.asn1ID);
memset(pasn1ID->data,0,32);
pasn1ID->length = 32;
memcpy(pasn1ID->data,g_pbASN,g_dwASN);
ccode = pfNWDSDefineAttr(context,
(PSTR)g_szAttributeNameA,
&AttrInfo);
if(ccode) {
if (ccode == ERR_ATTRIBUTE_ALREADY_EXISTS) {
ERR(("\nNWDSDefineAttr returned %X", ccode));
ERR(("The schema has been extended already\n", ccode));
WinError = 1;
BAIL();
}
ERR(("\nNWDSDefineAttr returned %X", ccode));
BAIL();
}
ccode = pfNWDSAllocBuf(DEFAULT_MESSAGE_LEN, &pInBuf);
if(ccode) {
ERR(("\nNWDSAllocBuf returned %X", ccode));
BAIL();
}
ccode = pfNWDSInitBuf(context, DSV_MODIFY_CLASS_DEF, pInBuf);
if(ccode) {
ERR(("\nNWDSInitBuf returned %X", ccode));
BAIL();
}
ccode = pfNWDSPutAttrName(context, pInBuf, (PSTR)g_szAttributeNameA);
if(ccode) {
ERR(("\nNWDSPutAttrName returned %X", ccode));
BAIL();
}
ccode = pfNWDSModifyClassDef(context, (PSTR)g_szClassA, pInBuf);
if(ccode) {
if (ccode == ERR_DUPLICATE_OPTIONAL) {
ERR(("\nNWDSPutAttrName returned %X\n",ccode));
ERR(("The schema has been extended already\n", ccode));
WinError = 1;
BAIL();
}
ERR(("\nNWDSPutAttrName returned %X", ccode));
BAIL();
}
error:
if (fLogout & fLoggedIn) {
DEBUGOUT(("We are logging out.\n",strName));
pfNWDSLogout(context);
}
if (pInBuf)
pfNWDSFreeBuf(pInBuf);
if (context)
pfNWDSFreeContext(context);
if (fFreeUnicodeTable)
pfNWFreeUnicodeTables();
if (pszServer)
MemFree(pszServer);
if (pszContext)
MemFree(pszContext);
if (pszUser)
MemFree(pszUser);
if (pszPasswd)
MemFree(pszPasswd);
if (WinError == 0 && (ccode != 0)) {
WinError = ERROR_EXTENDED_ERROR;
SelectivePrint(MSG_NETWARE_ERROR,ccode);
}
return WinError;
}
DWORD LoadNetwareDLLs()
{
DWORD WinError = 0;
calwin32LibraryHandle = LoadLibraryA("calwin32.DLL");
if (calwin32LibraryHandle == NULL) {
WinError = GetLastError();
ERR(("loadlib failed with %d\n,WinError"));
BAIL();
}
locwin32LibraryHandle = LoadLibraryA("locwin32.DLL");
if (locwin32LibraryHandle == NULL) {
WinError = GetLastError();
ERR(("loadlib failed with %d\n,WinError"));
BAIL();
}
netwin32LibraryHandle = LoadLibraryA("netwin32.DLL");
if (netwin32LibraryHandle == NULL) {
WinError = GetLastError();
ERR(("loadlib failed with %d\n,WinError"));
BAIL();
}
pfNWCallsInit = (PF_NWCallsInit) GetProcAddress(
calwin32LibraryHandle,
"NWCallsInit");
if (pfNWCallsInit == NULL) {
WinError = GetLastError();
ERR(("getprocaddress failed with %d\n,WinError"));
BAIL();
}
pfNWFreeUnicodeTables = (PF_NWFreeUnicodeTables) GetProcAddress(
locwin32LibraryHandle,
"NWFreeUnicodeTables");
if (pfNWFreeUnicodeTables == NULL) {
WinError = GetLastError();
ERR(("getprocaddress failed with %d\n,WinError"));
BAIL();
}
pfNWInitUnicodeTables = (PF_NWInitUnicodeTables) GetProcAddress(
locwin32LibraryHandle,
"NWInitUnicodeTables");
if (pfNWInitUnicodeTables == NULL) {
WinError = GetLastError();
ERR(("getprocaddress failed with %d\n,WinError"));
BAIL();
}
pfNWLlocaleconv = (PF_NWLlocaleconv) GetProcAddress(
locwin32LibraryHandle,
"NWLlocaleconv");
if (pfNWLlocaleconv == NULL) {
WinError = GetLastError();
ERR(("getprocaddress failed with %d\n,WinError"));
BAIL();
}
pfNWDSFreeContext = (PF_NWDSFreeContext) GetProcAddress(
netwin32LibraryHandle,
"NWDSFreeContext");
if (pfNWDSFreeContext == NULL) {
WinError = GetLastError();
ERR(("getprocaddress failed with %d\n,WinError"));
BAIL();
}
pfNWDSFreeBuf = (PF_NWDSFreeBuf) GetProcAddress(
netwin32LibraryHandle,
"NWDSFreeBuf");
if (pfNWDSFreeBuf == NULL) {
WinError = GetLastError();
ERR(("getprocaddress failed with %d\n,WinError"));
BAIL();
}
pfNWDSLogout = (PF_NWDSLogout) GetProcAddress(
netwin32LibraryHandle,
"NWDSLogout");
if (pfNWDSLogout == NULL) {
WinError = GetLastError();
ERR(("getprocaddress failed with %d\n,WinError"));
BAIL();
}
pfNWDSGetAttrDef = (PF_NWDSGetAttrDef) GetProcAddress(
netwin32LibraryHandle,
"NWDSGetAttrDef");
if (pfNWDSGetAttrDef == NULL) {
WinError = GetLastError();
ERR(("getprocaddress failed with %d\n,WinError"));
BAIL();
}
pfNWDSGetAttrCount = (PF_NWDSGetAttrCount) GetProcAddress(
netwin32LibraryHandle,
"NWDSGetAttrCount");
if (pfNWDSGetAttrCount == NULL) {
WinError = GetLastError();
ERR(("getprocaddress failed with %d\n,WinError"));
BAIL();
}
pfNWDSReadAttrDef = (PF_NWDSReadAttrDef) GetProcAddress(
netwin32LibraryHandle,
"NWDSReadAttrDef");
if (pfNWDSReadAttrDef == NULL) {
WinError = GetLastError();
ERR(("getprocaddress failed with %d\n,WinError"));
BAIL();
}
pfNWDSPutAttrName = (PF_NWDSPutAttrName) GetProcAddress(
netwin32LibraryHandle,
"NWDSPutAttrName");
if (pfNWDSPutAttrName == NULL) {
WinError = GetLastError();
ERR(("getprocaddress failed with %d\n,WinError"));
BAIL();
}
pfNWDSInitBuf = (PF_NWDSInitBuf) GetProcAddress(
netwin32LibraryHandle,
"NWDSInitBuf");
if (pfNWDSInitBuf == NULL) {
WinError = GetLastError();
ERR(("getprocaddress failed with %d\n,WinError"));
BAIL();
}
pfNWDSAllocBuf = (PF_NWDSAllocBuf) GetProcAddress(
netwin32LibraryHandle,
"NWDSAllocBuf");
if (pfNWDSAllocBuf == NULL) {
WinError = GetLastError();
ERR(("getprocaddress failed with %d\n,WinError"));
BAIL();
}
pfNWDSLogin = (PF_NWDSLogin) GetProcAddress(
netwin32LibraryHandle,
"NWDSLogin");
if (pfNWDSLogin == NULL) {
WinError = GetLastError();
ERR(("getprocaddress failed with %d\n,WinError"));
BAIL();
}
pfNWDSSetContext = (PF_NWDSSetContext) GetProcAddress(
netwin32LibraryHandle,
"NWDSSetContext");
if (pfNWDSSetContext == NULL) {
WinError = GetLastError();
ERR(("getprocaddress failed with %d\n,WinError"));
BAIL();
}
pfNWDSGetContext = (PF_NWDSGetContext) GetProcAddress(
netwin32LibraryHandle,
"NWDSGetContext");
if (pfNWDSGetContext == NULL) {
WinError = GetLastError();
ERR(("getprocaddress failed with %d\n,WinError"));
BAIL();
}
pfNWIsDSAuthenticated = (PF_NWIsDSAuthenticated) GetProcAddress(
netwin32LibraryHandle,
"NWIsDSAuthenticated");
if (pfNWIsDSAuthenticated == NULL) {
WinError = GetLastError();
ERR(("getprocaddress failed with %d\n,WinError"));
BAIL();
}
pfNWDSCreateContext = (PF_NWDSCreateContext) GetProcAddress(
netwin32LibraryHandle,
"NWDSCreateContext");
if (pfNWDSCreateContext == NULL) {
WinError = GetLastError();
ERR(("getprocaddress failed with %d\n,WinError"));
BAIL();
}
pfNWDSModifyClassDef = (PF_NWDSModifyClassDef) GetProcAddress(
netwin32LibraryHandle,
"NWDSModifyClassDef");
if (pfNWDSModifyClassDef == NULL) {
WinError = GetLastError();
ERR(("getprocaddress failed with %d\n,WinError"));
BAIL();
}
pfNWDSDefineAttr = (PF_NWDSDefineAttr) GetProcAddress(
netwin32LibraryHandle,
"NWDSDefineAttr");
if (pfNWDSDefineAttr== NULL) {
WinError = GetLastError();
ERR(("getprocaddress failed with %d\n,WinError"));
BAIL();
}
error:
return WinError;
}